Skip to content

Quick Start

Installation

To install this library, simply use your favorite package manager, here we use pure pip.

pip install monad-std

Then, import the library:

1
2
3
>>> from monad_std.prelude import *
>>> Ok(2)
Result::Ok(2)

Now you could use the utilities this library provides. For more information and examples, see the api documentation.

Using monads

Option

Options refers to a value which can be a None. Instead of using Python's Optional[T], monad_std.Option[T] provides a wrapped nullable value, which is also capable of representing a Option::Some(None) that Python's current solution cannot. To use this, simply import it:

from monad_std import Option

And create value like this:

1
2
3
from monad_std.prelude import *
Option.some(3) # This will create a box containing a `3`
Option.none()  # This will produce a ZST value, representing the `None` in `monad_std`

For more information, see the documentation: monad-std: Option.

Homework

1. Write a function which accepts a possibly empty number, and returns its square root if it exists.

Key
1
2
3
4
from monad_std.prelude import *
import math
def solution(v: Option[float]) -> Option[float]:
    return v.and_then(lambda x: Option.some(math.sqrt(x)) if x >= 0 else Option.none())

2. Write a function that accepts two nullable number and returns their sum. If one of the number is null, use 0 as a fallback.

Key
1
2
3
from monad_std.prelude import *
def solution(v1: Option[float], v2: Option[float]) -> Option[float]:
    return v1.and_then(lambda x: Option.some(x + v2.unwrap_or(0))).or_else(lambda: v2)

Result

Results refers to a result of something, possibly a successful value or an error. Both value can be any type. Instead of using Python's exceptions and try-catch patterns, this can force you to check all potential exceptions and error, and throw them explicitly. You can use this just like the Option:

from monad_std import Result, Err, Ok

Values can be created via both Result's static methods and Err or Ok.

1
2
3
4
5
6
7
8
9
from monad_std.prelude import *

# The following two operations are equivalent
Result.of_ok(2)
Ok(2)

# The following two operations are equivalent
Result.of_err('error')
Err('error')

For more information, see the documentation: monad-std: Result.

Note: Results can be transformed into Options via the Result.ok and Result.err method.

1
2
3
4
5
6
from monad_std.prelude import *

print(repr(Ok(2).ok()), repr(Ok(2).err()))
# Output: Option::Some(2) Option::None
print(repr(Err('err').err()), repr(Err('err').ok()))
# Output: Option::Some(err) Option::None

Note: You can catch a Python styled exception by using Result.catch or Result.catch_from static methods, which accept a function call and return a result, containing the raised exception:

from monad_std.prelude import *
from math import sqrt

def maybe_raise_exception(value: float) -> float:
    return sqrt(value)

print(repr(Result.catch(lambda: maybe_raise_exception(-1))))
# Output: Result::Err(math domain error)
print(repr(Result.catch_from(maybe_raise_exception, -1)))
# Output: Result::Err(math domain error)

Using Advanced Iterators

The iterator can be used through the IterMeta abstract class(as an entry point):

from monad_std.iter impot IterMeta # Basic iterator class
from monad_std.prelude import siter, once # Iterator constructor

An iterator can be constructed by passing any iterator or iterable objects, or a single value(once):

1
2
3
4
5
6
from monad_std.prelude import *
# construct from iterator/iterable
siter([1, 2, 4])
siter(range(10))
# construct from a single value
once(5)

The iterator is lazily calculated, so call collect if you want to get the result:

  • IterMeta.collect_list: collect everything in the iterator into a list, stopping at the first Option::None.
  • IterMeta.collect_tuple: collect everything in the iterator into a tuple, stopping at the first Option::None.
  • IterMeta.collect_string: joining the iterator into a string, calling __str__ and falling back to __repr__, stopping at the first Option::None.
  • IterMeta.collect_array: collect the iterator into funct.Array. funct is another library which enhanced the Python's builtin list. If you need to use this functionality, you should first install that lib.

For more information, see the documentation: monad-std: Iterator.

Homework

1. Write a function that accepts a list of positive integers, and returns those integers that can be devided exactly by 3 and 5.

Key
1
2
3
from monad_std.prelude import *
def solution(v: list) -> list:
    return siter(v).filter(lambda x: x % 3 == 0 and x % 5 == 0).collect_list()

2. Write a function that accepts a list of positive integers, returns a list with flattened items of the intenger and its double.

Example:
Input: range(10)
Output: [0, 0, 1, 2, 2, 4, 3, 6, 4, 8, 5, 10, 6, 12, 7, 14, 8, 16, 9, 18]

Key
1
2
3
from monad_std.prelude import *
def solution(v: list) -> list:
    return siter(v).flat_map(lambda x: [x, x * 2]).collect_list()