Welcome to pyMonet’s documentation¶
High abstract python library for functional programming. Contains algebraic data structures known (or unknown) from Haskell or Scala. With MIT licence.
Box¶
from pymonet.box import Box
box = Box(42) # Box<42>
(box
.map(lambda value: value + 1) # Box<43>
.map(lambda value: str(value)) # Box<"43">
.map(lambda value: value[::-1]) # Box<"34">
.bind(lambda value: "output = " + value)) # "output = 34"
-
class
pymonet.box.
Box
(value: T)¶ Data type for storage any type of data
-
ap
(applicative)¶ Applies the function inside the Box[A] structure to another applicative type.
-
bind
(mapper: Callable[[T], U]) → U¶ Take function and applied this function on current box value and returns mapped value.
- Parameters
mapper (Function(A) -> B) – mapper function
- Returns
new box with mapped value
- Return type
B
-
map
(mapper: Callable[[T], U]) → pymonet.box.Box[~U][U]¶ Take function (A) -> b and applied this function on current box value and returns new box with mapped value.
- Parameters
mapper (Function(A) -> B) – mapper function
- Returns
new box with mapped value
- Return type
Box[B]
-
to_either
()¶ Transform Box into Right either.
- Returns
right Either monad with previous value
- Return type
Right[A]
-
to_lazy
()¶ Transform Box into Lazy with returning value function.
- Returns
not folded Lazy monad with function returning previous value
- Return type
Lazy[Function(() -> A)]
-
to_maybe
()¶ Transform Box into not empty Maybe.
- Returns
non empty Maybe monad with previous value
- Return type
Maybe[A]
-
to_try
()¶ Transform Box into successfull Try.
- Returns
successfull Try monad with previous value
- Return type
Try[A]
-
to_validation
()¶ Transform Box into Validation.
- Returns
successfull Validation monad with previous value
- Return type
Validation[A, []]
-
Either¶
from pymonet.either import Left, Right
from pymonet.utils import identity
def divide(divided, divider):
if divider == 0:
return Left('can not divide by 0')
return Right(divided, divider)
def handle_error(value):
print ('error {}'.format(value))
def handle_success(value):
print ('success {}'.format(value))
(divide(42, 0)
.map(lambda value: value + 1)
.bind(lambda value: Right(value + 1))
.case(error=handle_error, success=handle_success))
# error 42
(divide(42, 1)
.map(identity, lambda value: value + 1)
.bind(lambda value: Right(value + 1))
.case(error=handle_error, success=handle_success))
# success 44
-
class
pymonet.either.
Left
(value: T)¶ Not successfully Either
-
bind
(_) → pymonet.either.Left[~T][T]¶ Take mapper function and return value of Left.
- Returns
Stored value
- Return type
A
-
is_left
() → bool¶ - Returns
True
- Return type
Boolean
-
is_right
() → bool¶ - Returns
False
- Return type
Boolean
-
map
(_: Callable[[Any], Any]) → pymonet.either.Left[~T][T]¶ Take mapper function and return new instance of Left with the same value.
- Returns
Copy of self
- Return type
Left[A]
-
to_lazy
()¶ Transform Either to Try.
- Returns
Lazy monad with function returning previous value
- Return type
Lazy[Function() -> A]
-
to_try
()¶ Transform Either to Try.
- Returns
resolved Try monad with previous value. Right is resolved successfully, Left not.
- Return type
Box[A]
-
to_validation
()¶ Transform Box into Validation.
- Returns
failed Validation monad with previous value as error
- Return type
Validation[None, [A]]
-
-
class
pymonet.either.
Right
(value: T)¶ Not successfully Either
-
ap
(applicative)¶ Applies the function inside the Either[A] structure to another applicative type.
- Parameters
applicative (Either[B]) – applicative contains function
- Returns
new Either with result of contains function
- Return type
Either[A(B)]
-
bind
(mapper: Callable[[T], U]) → U¶ Take mapper function and returns result of them called with Right value.
- Parameters
mapper (Function(A) -> Either[B]) – function to apply on Right value
- Returns
result of mapper
- Return type
Either[B]
-
is_left
() → bool¶ - Returns
False
- Return type
Boolean
-
is_right
() → bool¶ - Returns
True
- Return type
Boolean
-
map
(mapper: Callable[[T], U]) → pymonet.either.Either[~U][U]¶ Take mapper function and return new instance of Right with mapped value.
- Parameters
mapper (Function(A) -> B) – function to apply on Right value
- Returns
new Right with result of mapper
- Return type
Right[B]
-
to_lazy
()¶ Transform Either to Try.
- Returns
Lazy monad with function returning previous value
- Return type
Lazy[Function() -> A]
-
to_try
()¶ Transform Either to Try.
- Returns
resolved Try monad with previous value. Right is resolved successfully, Left not.
- Return type
Box[A]
-
to_validation
()¶ Transform Either into Validation.
- Returns
successfull Validation monad with previous value
- Return type
Validation[A, []]
-
Maybe¶
from pymonet.Maybe import Maybe
def get_index(item):
if item in [1,2,3]:
return Maybe.just(42)
return Maybe.nothing()
get_index(42).get_or_else(0) # 0
get_index(1).get_or_else(0) # 3
get_index(42)\
.map(lambda value: value + 1)\
.bind(lambda value: Maybe.just(value + 1))\
.get_or_else(0)
# 0
get_index(1)\
.map(lambda value: value + 1)\
.bind(lambda value: Maybe.just(value + 1))\
.get_or_else(0)
get_index(42)\
.filter(lambda value: value % 2 == 0)\
.get_or_else(0)
# 0
get_index(3)\
.filter(lambda value: value % 2 == 0)\
.get_or_else(0)
# 0
get_index(2)\
.filter(lambda value: value % 2 == 0)\
.get_or_else(0)
# 2
-
class
pymonet.maybe.
Maybe
(value: T, is_nothing: bool)¶ Maybe type is the most common way of representing nothingness (or the null type). Maybe is effectively abstract and has two concrete subtypes: Box (also Some) and Nothing.
-
bind
(mapper: Callable[[T], Maybe[U]]) → Union[pymonet.maybe.Maybe[~U][U], pymonet.maybe.Maybe[NoneType][None]]¶ If Maybe is empty return new empty Maybe, in other case takes mapper function and returns result of mapper.
- Parameters
mapper (Function(A) -> Maybe[B]) – function to call with Maybe.value
- Returns
Maybe[B | None]
-
filter
(filterer: Callable[[T], bool]) → Union[pymonet.maybe.Maybe[~T][T], pymonet.maybe.Maybe[NoneType][None]]¶ If Maybe is empty or filterer returns False return default_value, in other case return new instance of Maybe with the same value.
- Parameters
filterer (Function(A) -> Boolean) –
- Returns
copy of self when filterer returns True, in other case empty Maybe
- Return type
Maybe[A] | Maybe[None]
-
get_or_else
(default_value: U) → Union[T, U]¶ If Maybe is empty return default_value, in other case.
- Parameters
default_value (Any) – value to return if Maybe is empty
- Returns
value of Maybe or default_value
- Return type
A
-
classmethod
just
(value: T) → pymonet.maybe.Maybe[~T][T]¶ Create not empty maybe.
- Parameters
mapper (Any) – value to store in Maybe
- Returns
Maybe[Any]
-
map
(mapper: Callable[[T], U]) → Union[pymonet.maybe.Maybe[~U][U], pymonet.maybe.Maybe[NoneType][None]]¶ If Maybe is empty return new empty Maybe, in other case takes mapper function and returns new instance of Maybe with result of mapper.
- Parameters
mapper (Function(A) -> B) – function to call with Maybe value
- Returns
Maybe[B | None]
-
classmethod
nothing
() → pymonet.maybe.Maybe[NoneType][None]¶ Create empty maybe.
- Returns
Maybe[None]
-
to_box
()¶ Transform Maybe to Box.
- Returns
Box monad with previous value when Maybe is not empty, in other case Box with None
- Return type
Box[A | None]
-
to_either
()¶ Transform Maybe to Either.
- Returns
Right monad with previous value when Maybe is not empty, in other case Left with None
- Return type
Either[A | None]
-
to_lazy
()¶ Transform Maybe to Try.
- Returns
Lazy monad with function returning previous value in other case Left with None
- Return type
Lazy[Function() -> (A | None)]
-
to_try
()¶ Transform Maybe to Try.
- Returns
successfully Try with previous value when Maybe is not empty, othercase not successfully Try with None
- Return type
Try[A]
-
to_validation
()¶ Transform Maybe into Validation.
- Returns
successfull Validation monad with previous value or None when Maybe is empty
- Return type
Validation[A, []]
-
Lazy¶
from pymonet.lazy import Lazy
def fn():
print('fn call')
return 42
def mapper(value):
print('mapper side effect of ' + value)
return value + 1
def side_effect(value):
print('side effect of ' + value)
# Lazy instances memoize output of constructor function
lazy = Lazy(fn)
mapped_lazy = lazy.map(mapper)
mapped_lazy.fold(side_effect)
# fn call
# mapper side effect of 42
# side effect of 42
lazy = Lazy(fn)
value1 = lazy.get()
# fn call
value2 = lazy.get()
print(value1, value2)
# 42, 42
-
class
pymonet.lazy.
Lazy
(constructor_fn: Callable[[T], U])¶ Data type for storage any type of function. This function (and all his mappers) will be called only during calling fold method
-
__eq__
(other: object) → bool¶ Two Lazy are equals where both are evaluated both have the same value and constructor functions.
-
__init__
(constructor_fn: Callable[[T], U]) → None¶ - Parameters
constructor_fn (Function() -> A) – function to call during fold method call
-
bind
(fn: Callable[[U], pymonet.lazy.Lazy[~U, ~W][U, W]]) → pymonet.lazy.Lazy[~T, ~W][T, W]¶ Take function and call constructor function passing returned value to fn function.
It’s only way to call function store in Lazy :param fn: Function(constructor_fn) -> B :returns: result od folder function :rtype: B
-
get
(*args)¶ Evaluate function and memoize her output or return memoized value when function was evaluated.
- Returns
result of function in Lazy
- Return type
A
-
map
(mapper: Callable[[U], W]) → pymonet.lazy.Lazy[~T, ~W][T, W]¶ Take function Function(A) -> B and returns new Lazy with mapped result of Lazy constructor function. Both mapper end constructor will be called only during calling fold method.
- Parameters
mapper (Function(A) -> B) – mapper function
- Returns
Lazy with mapped value
- Return type
Lazy[Function() -> B)]
-
classmethod
of
(value: U) → pymonet.lazy.Lazy[~T, ~U][T, U]¶ Returns Lazy with function returning argument.
- Parameters
value (Any) – value to return by Lazy constructor_fn
- Returns
Lazy with function returning argument
- Return type
Lazy[Function() -> A]
-
to_validation
(*args)¶ Transform Lazy into successful Validation with constructor_fn result.
- Returns
successfull Validation monad with previous value
- Return type
Validation[A, []]
-
Try¶
from pymonet.monad_try import Try
def divide(dividend, divisor):
return dividend / divisor
def success_callback(value):
print('success: {}'.format(value))
def fail_callback(error):
print('error: {}'.format(value))
(Try.of(divide, 42, 2)
.on_success(success_callback)
.on_fail(fail_callback))
# success: 21
(Try.of(divide, 42, 0)
.on_success(success_callback)
.on_fail(fail_callback))
#error: division by zero
# map method will be only applied mapper when exception was not thrown
(Try.of(divide, 42, 2)
.map(lambda value: value + 1)
.on_success(success_callback)
.on_fail(fail_callback))
# success: 22
(Try.of(divide, 42, 0)
.on_success(success_callback)
.map(lambda value: value + 1)
.on_fail(fail_callback))
#error: division by zero
# get_or_else method returns value when exception was not thrown
Try.of(divide, 42, 2).get_or_else('Holy Grail') # 21
Try.of(divide, 42, 0).get_or_else('Holy Grail') # 'Holy Grail'
# get method should return value with or without exception thrown
Try.of(divide, 42, 2).get() # 21
Try.of(divide, 42, 0).get() # ZeroDivisionError<'division by zero'>
-
class
pymonet.monad_try.
Try
(value, is_success: bool)¶ The Try control gives us the ability write safe code without focusing on try-catch blocks in the presence of exceptions.
-
bind
(binder)¶ Take function and applied this function with monad value and returns function result.
- Params binder
function to apply on monad value
- Returns
for successfully result of binder, othercase copy of self
- Return type
Try[B]
-
filter
(filterer)¶ Take filterer function, when monad is successfully call filterer with monad value. When filterer returns True method returns copy of monad, othercase not successfully Try with previous value.
- Params filterer
function to apply on monad value
- Returns
Try with previous value
- Return type
Try[A]
-
get
()¶ Return monad value.
- Returns
monad value
- Return type
A
-
get_or_else
(default_value)¶ Return monad value when is successfully. Othercase return default_value argument.
- Params default_value
value to return when monad is not successfully.
- Returns
monad value
- Return type
A | B
-
map
(mapper)¶ Take function and applied this function with monad value and returns new monad with mapped value.
- Params mapper
function to apply on monad value
- Returns
for successfully new Try with mapped value, othercase copy of self
- Return type
Try[B]
-
classmethod
of
(fn: Callable, *args)¶ Call argument function with args in try-catch. when function don’t raise exception, not successfully when raise.
-
Task¶
from pymonet.task import Task
def resolvable_fn(reject, resolve):
print('resolve side effect')
resolve(42)
def rejectable_fn(reject, resolve):
print('reject side effect')
reject(0)
resolvable_task = Task.of(resolvable_fn)
rejectable_task = Task.of(rejectable_fn)
# map method will be applied only on resolvable tasks during calling bind method
resolvable_task.map(lambda value: value + 1) # Task<() -> 43>
rejectable_task.map(lambda value: value + 1) # Task<() -> 0>
# bind method will be applied only on resolvable tasks. bind also will call stored function
def mapper(value):
print('mapper side effect ' + value)
return value + 1
resolvable_task.bind(mapper)
# resolve side effect
# mapper side effect 42
rejectable_task.bind(mapper)
# reject side effect
-
class
pymonet.task.
Task
(fork)¶ Task are data-type for handle execution of functions (in lazy way) transform results of this function and handle errors.
-
__init__
(fork)¶ - Parameters
fork (Function(reject, resolve) -> Any) – function to call during fork
-
bind
(fn)¶ Take function, store it and call with Task value during calling fork function. Return result of called.
- Parameters
fn (Function(value) -> Task[reject, mapped_value]) – mapper function
- Returns
new Task with mapper resolve attribute
- Return type
Task[reject, mapped_value]
-
map
(fn)¶ Take function, store it and call with Task value during calling fork function. Return new Task with result of called.
- Parameters
fn (Function(value) -> B) – mapper function
- Returns
new Task with mapped resolve attribute
- Return type
Task[Function(resolve, reject -> A | B]
-
Validation¶
from pymonet.validation import Validation
def test_validation_is_fail():
assert Validation.fail(['fail']).is_fail()
def validate_length(value):
if len(value) < 5:
return Validation.fail(['value not long enough'])
return Validation.success()
def validate_uppercase(value):
if value[0].upper() != value[0]:
return Validation.fail(['value not uppercase'])
return Validation.success()
def validate_contains_special_character(value):
if re.match(r'^[a-zA-Z0-9_]*$', value):
return Validation.fail(['value not contains special character'])
return Validation.success()
def validate(value):
return (Validation.success(value)
.ap(validate_length)
.ap(validate_uppercase)
.ap(validate_contains_special_character))
validate('Success$') # Validation['Success$', []]
validate('Success') # Validation['Success$', ['value not uppercase']]
validate('S$') # Validation['Success$', ['value not long enough']]
validate('s$') # Validation['Success$', ['value not long enough', 'value not uppercase']]
validate('s') # Validation['Success$', ['value not long enough', 'value not uppercase', 'value not contains special character']]
-
class
pymonet.validation.
Validation
(value, errors)¶ It that can hold either a success value or a failure value and has methods for accumulating errors
-
__eq__
(other)¶ Two Validations are equals when values and errors lists are equal.
-
ap
(fn)¶ It takes as a parameter function returning another Validation. Function is called with Validation value and returns new Validation with previous value and concated new and old errors.
- Parameters
monad (Function(A) -> Validation[Any, List[E]]) – monad contains function
- Returns
new validation with stored errors
- Return type
Validation[A, List[E]]
-
bind
(folder)¶ Take function and applied this function on current Validation value and returns folder result.
- Parameters
mapper (Function(A) -> Validation[B, E]) – mapper function
- Returns
new Validation with mapped value
- Return type
Validation[B, E]
-
classmethod
fail
(errors=[])¶ Returns failed Validation with None as value and errors list.
- Params errors
list of errors to store
- Returns
Failed Validation
- Return type
Validation[None, List[E]]
-
is_fail
()¶ Returns True when errors list are not empty.
- Returns
True for empty errors not list
- Return type
Boolean
-
is_success
()¶ Returns True when errors list are empty.
- Returns
True for empty errors list
- Return type
Boolean
-
map
(mapper)¶ Take function (A) -> B and applied this function on current Validation value.
- Parameters
mapper (Function(A) -> B) – mapper function
- Returns
new Validation with mapped value and previous errors
- Return type
Validation[B, List[E]]
-
classmethod
success
(value=None)¶ Returns successful Validation with value and empty errors list.
- Params value
value to store in Validation
- Returns
Successful Validation
- Return type
Validation[A, []]
-
to_either
()¶ Transform Validation to Either.
- Returns
Right monad with previous value when Validation has no errors, in other case Left with errors list
- Return type
Right[A] | Left[E]
-
to_lazy
()¶ Transform Validation to Try.
- Returns
Lazy monad with function returning Validation value
- Return type
Lazy[Function() -> (A | None)]
-
ImmutableList¶
from pymonet.immutable_list import ImmutableList
from pymonet.utils import increase
- =
lst = ImmutableList.of(1, 2, 3)
lst.map(increase) # ImmutableList.of(2, 3, 4) lst.filter(lambda item: item % 2 == 0) # ImmutableList.of(2) lst.find(lambda item: item % 2 == 0) # 2 lst.map(increase) # ImmutableList.of(2, 3, 4)
-
class
pymonet.immutable_list.
ImmutableList
(head: T = None, tail: Optional[pymonet.immutable_list.ImmutableList[~T][T]] = None, is_empty: bool = False)¶ Immutable list is data structure that doesn’t allow to mutate instances
-
__add__
(other: pymonet.immutable_list.ImmutableList[~T][T]) → pymonet.immutable_list.ImmutableList[~T][T]¶ If Maybe is empty return new empty Maybe, in other case takes mapper function and returns result of mapper.
- Parameters
mapper (Function(A) -> Maybe[B]) – function to call with Maybe.value
- Returns
Maybe[B | None]
-
append
(new_element: T) → pymonet.immutable_list.ImmutableList[~T][T]¶ Returns new ImmutableList with elements from previous one and argument value on the end of list
- Parameters
new_element – element to append on the end of list
- Returns
ImmutableList[A]
-
filter
(fn: Callable[[Optional[T]], bool]) → pymonet.immutable_list.ImmutableList[~T][T]¶ Returns new ImmutableList with only this elements that passed info argument returns True
- Parameters
fn (Function(A) -> bool) – function to call with ImmutableList value
- Returns
ImmutableList[A]
-
find
(fn: Callable[[Optional[T]], bool]) → Optional[T]¶ Returns first element of ImmutableList that passed info argument returns True
- Parameters
fn (Function(A) -> bool) – function to call with ImmutableList value
- Returns
A
-
map
(fn: Callable[[Optional[T]], U]) → pymonet.immutable_list.ImmutableList[~U][U]¶ Returns new ImmutableList with each element mapped into result of argument called with each element of ImmutableList
- Parameters
fn (Function(A) -> B) – function to call with ImmutableList value
- Returns
ImmutableList[B]
-
unshift
(new_element: T) → pymonet.immutable_list.ImmutableList[~T][T]¶ Returns new ImmutableList with argument value on the begin of list and other list elements after it
- Parameters
new_element – element to append on the begin of list
- Returns
ImmutableList[A]
-
Semigroups¶
from pymonet.semigroups import All, First, Map, Sum
All(True).concat(All(False)) # All<False>
All(True).concat(All(True)) # All<True>
All(True) == All(True) # True
All(True) == All(False) # False
ingredient1 = Map({'score': Sum(1), 'won': All(True), 'captain': First('captain america')})
ingredient2 = Map({'score': Sum(2), 'won': All(True), 'captain': First('iron man')})
ingredient1.concat(ingredient2) # Map<{'score': Sum(3), 'won': All(True), 'captain': First('captain america')}>
-
class
pymonet.semigroups.
All
(value)¶ All is a Monoid that will combine 2 values of any type using logical conjunction on their coerced Boolean values.
-
__init__
(value)¶ Initialize self. See help(type(self)) for accurate signature.
-
-
class
pymonet.semigroups.
One
(value)¶ One is a Monoid that will combine 2 values of any type using logical disjunction OR on their coerced Boolean values.
-
__init__
(value)¶ Initialize self. See help(type(self)) for accurate signature.
-
-
class
pymonet.semigroups.
First
(value)¶ First is a Monoid that will always return the first, value when 2 First instances are combined.
-
__init__
(value)¶ Initialize self. See help(type(self)) for accurate signature.
-
-
class
pymonet.semigroups.
Last
(value)¶ Last is a Monoid that will always return the lastest, value when 2 Last instances are combined.
-
__init__
(value)¶ Initialize self. See help(type(self)) for accurate signature.
-
-
class
pymonet.semigroups.
Map
(value)¶ Map is a Semigroup that will always return contated all values inside Map value
-
__init__
(value)¶ Initialize self. See help(type(self)) for accurate signature.
-
-
class
pymonet.semigroups.
Max
(value)¶ Max is a Monoid that will combines 2 numbers, resulting in the largest of the two.
-
__init__
(value)¶ Initialize self. See help(type(self)) for accurate signature.
-
Utils¶
-
pymonet.utils.
identity
(value: T) → T¶ Return first argument.
- Parameters
value (Any) –
- Returns
- Return type
Any
-
pymonet.utils.
increase
(value: int) → int¶ Return increased by 1 argument.
- Parameters
value (Int) –
- Returns
- Return type
Int
-
pymonet.utils.
eq
(*args)¶
-
pymonet.utils.
curried_map
(*args)¶
-
pymonet.utils.
curried_filter
(*args)¶
-
pymonet.utils.
compose
(value, *functions)¶ Perform right-to-left function composition.
- Parameters
value (Any) – argument of first applied function
functions (List[Function]) – list of functions to applied from right-to-left
- Returns
result of all functions
- Return type
Any
from pymonet.utils import \
increase,\
compose,\
curried_map as map,\
curried_filter as filter
compose(
list(range(10)),
map(increase),
filter(is_odd)
)
#[1, 3, 5, 7, 9]
-
pymonet.utils.
pipe
(value, *functions)¶ Perform left-to-right function composition.
- Parameters
value (Any) – argument of first applied function
functions (List[Function]) – list of functions to applied from left-to-right
- Returns
result of all functions
- Return type
Any
from pymonet.utils import increase, pipe
pipe(42, increase, lambda value: value * 2)
#86
-
pymonet.utils.
curry
(x, args_count=None)¶ In mathematics and computer science, currying is the technique of translating the evaluation of a function. It that takes multiple arguments (or a tuple of arguments) into evaluating a sequence of functions. each with a single argument.
from pymonet.utils import curry
@curry
def fn(arg1, arg2, arg3):
return arg1 + arg2 + arg3
fn(1)(2)(3) # 6
fn(1, 2)(3) # 6
fn(1)(2, 3) # 6
fn(1, 2, 3) # 6
-
pymonet.utils.
cond
(condition_list: List[Tuple[Callable[[T], bool], Callable]])¶ Function for return function depended on first function argument cond get list of two-item tuples, first is condition_function, second is execute_function. Returns this execute_function witch first condition_function return truly value.
- Parameters
condition_list (List[(Function, Function)]) – list of two-item tuples (condition_function, execute_function)
- Returns
Returns this execute_function witch first condition_function return truly value
- Return type
Function
from pymonet.utils import cond
fn = cond([
(lambda arg: arg == 0, lambda: 'first'),
(lambda arg: arg == 1, lambda: 'second'),
(lambda arg: arg == 2, lambda: 'third').
])
fn(1) # second
# lambda arg: arg == 2 will not be call
-
pymonet.utils.
memoize
(fn: Callable, key=<function curry.<locals>.fn>) → Callable¶ Create a new function that, when invoked, caches the result of calling fn for a given argument set and returns the result. Subsequent calls to the memoized fn with the same argument set will not result in an additional call to fn; instead, the cached result for that set of arguments will be returned.
- Parameters
fn (Function(A) -> B) – function to invoke
key (Function(A, A) -> Boolean) – function to decide if result should be taken from cache
- Returns
new function invoking old one
- Return type
Function(A) -> B
from pymonet.utils import memoize, eq
def fn(arg):
print('fn flag')
return arg + 1
memoized_fn = memoize(fn)
memoized_fn(42) # 43
# fn flag
memoized_fn(42) # 43
# print to called
memoized_fn(43) # 44
# fn flag