Actions

smonad.actions - useful monadic actions.

smonad.actions.ftry(failure_handler, success_handler=identity)[source]

Case analysis for Try.

This function is named ftry instead of try to avoid collision with the try keyword.

Returns a function that when called with a value of type Try, applies either failure_handler or success_handler to that value depending on the type of it. If an incompatible value is passed, a TypeError will be raised.

>>> def log(v):
...     print('Got Failure({})'.format(v))
>>> logger = ftry(failure_handler=log)
>>> logger(Failure(1))
Got Failure(1)
>>> logger(Success(1))
1
>>> def inc(v):
...     return v + 1
>>> act = ftry(log, inc)
>>> [act(v) for v in (Failure(0), Success(1), Failure(2), Success(3))]
Got Failure(0)
Got Failure(2)
[None, 2, None, 4]
smonad.actions.first(sequence, default=Nothing, predicate=None)[source]

Iterate over a sequence, return the first Just.

If predicate is provided, first returns the first item that satisfy the predicate, the item will be wrapped in a Just if it is not already, so that the return value of this function will be an instance of Maybe in all circumstances. Returns default if no satisfied value in the sequence, default defaults to Nothing.

>>> from smonad.types import Just, Nothing
>>> first([Nothing, Nothing, Just(42), Nothing])
Just(42)
>>> first([Just(42), Just(43)])
Just(42)
>>> first([Nothing, Nothing, Nothing])
Nothing
>>> first([])
Nothing
>>> first([Nothing, Nothing], default=Just(2))
Just(2)
>>> first([False, 0, True], predicate=bool)
Just(True)
>>> first([False, 0, Just(1)], predicate=bool)
Just(1)
>>> first([False, 0, ''], predicate=bool)
Nothing
>>> first(range(100), predicate=lambda x: x > 40 and x % 2 == 0)
Just(42)
>>> first(range(100), predicate=lambda x: x > 100)
Nothing

This is basically a customized version of msum for Maybe, a separate function like this is needed because there is no way to write a generic msum in python that cab be evaluated in a non-strict way. The obvious reduce(operator.add, sequence), albeit beautiful, is strict, unless we build up the sequence with generator expressions in-place.

Maybe (pun intended!) implemented as MonadOr instead of MonadPlus might be more semantically correct in this case.

smonad.actions.tryout(*functions)[source]

Combine functions into one.

Returns a monadic function that when called, will try out functions in functions one by one in order, testing the result, stop and return with the first value that is true or the last result.

>>> zero = lambda n: 'zero' if n == 0 else False
>>> odd = lambda n: 'odd' if n % 2 else False
>>> even = lambda n: 'even' if n % 2 == 0 else False
>>> test = tryout(zero, odd, even)
>>> test(0)
'zero'
>>> test(1)
'odd'
>>> test(2)
'even'
smonad.actions.attempt(callable, exception=None)[source]

Call callable and wrap it with appropriate Failure or Success

If calling the callable raises an exception, wrap the exception in a Failure. If the keyword argument exception is not None, only wrap the specified exception. Raise all other exceptions. The stacktrace related to the exception is added to the wrapped exception as the stractrace property

If the calling the callable does not raise an exception, return Success wrapping the value