Package: typed-monads
Type-safe MonadsThis is an experiment in building monads in Python supported by strict
type annotations. The goal is to be able to compose monads with the
type checker ensuring their correctness.MotivationI'm a fan of monads, but believe they work best with the support of a
strong type system. I've attempted to use libraries likePyMonad, but been frustrated by a
lack of type constraints preventing incorrect usage. I could've
attempted to add type annotations to one of those libraries, but
building my own is more fun.This is a fork of the original work byCorrel RoushI added some utility methods to make it easier to use in my day to day code and better interate with the pythonic style ( ieList Comprehension)Installation$pipinstalltyped-monadsDocumentationYou can findall the docs hereCurringMixing Higher order functions ( functions that return a function ) with moand is a very common programming style other functional programming languages.
Withcurrydecorator you can transform a function in acurriedfunction: just apss some positional parameters and get back a function with the remaining ones.@currydefpower(exp:int,base:int)->int:returnmath.pow(base,exp)square_fn=power(2)# a function that returns the square of the parameterBase ClassesFunctormap (*)Applies a function to the contents of a functor, transforming it from
one thing to another.The*operator implements map on functors, and is both left and
right associative:defwordcount(s:str):returnlen(s.split())f.map(wordcount)==wordcount*f==f*wordcountApplicativeExtendsFunctor.pureWraps a value in an applicative functor.e.g.:Maybe.pure("abc") == Just("abc")
Result.pure(123) == Ok(123)apply (&)Transforms the value contained in the instance's functor with a
function wrapped in the same type of functor.The&operator implements apply on applicatives, and is
right-associative.e.g.:increment=lambdax:x+1Just(3).apply(Just(increment))==Just(increment)&Just(3)==Just(4)This can be very handily combined with map to apply curried functions
to multiple arguments:subtract=lambdax:lambday:x-ysubtract*Just(10)&Just(4)==Just(6)MonadExtendsApplicative.bind (>>)Passes the value within the monad through an operation returning the
same type of monad, allowing multiple operations to be chained.The>>operator implements bind on monads, and is left-associative.@currydeflookup(key:str,dictionary:Dict[str,str])->Maybe[str]:try:returnJust(dictionary[key])exceptKeyError:returnNothing()result=Just({"hello":"world"}).bind(lookup("hello")).bind(lambdas:s.upper())result=(Just({"hello":"world"})>>lookup("hello")>>(lambdas:s.upper()))Monoidmappend (+)Describes an associative binary operation for a type.mzeroProvides an identity value for themappendoperation.mconcatAccumulates a list of values usingmappend. Returns themzerovalue if the list is empty.MonadsWrapped values should be immutable: they areprotectedfrom accidental direct writing withFinaltype and the pythonic naming convention.Maybe[T]Represents optional data. AMaybeinstance of a certain typeTwill
either be aJustobject wrapping a value of that type, orNothing.Mapping a function overNothingwill returnNothingwithout
calling the function.Binding an operation with aNothingwill returnNothingwithout
attempting the operation.Result[T, E]Represents a state of success or failure, declaring a type for each. AResultinstance will either be anOkobject wrapping a value of
the success typeT, or anErrobject wrapping a value of the
failure typeE.Mapping a function over anErrwill return theErrunchanged
without calling the function.Binding an operation with anErrwill return theErrunchanged
without attempting the operation.List[T]Represents a ordered sequence of items.Also implementsMonoid.Set[T]Represents a unordered sequence of unique items.Also implementsMonoid.Future[T]Represents an asynchronous action.Also implementsAwaitable.Reader[T]Represents the application of a function to it's argument.Monads as iterableIt is handy to iterate over some monad contents.Listis obliviously the first candidate:m_list:List[int]=List([1,2,4,9])foriinm_list:...#Or filter with a generatorevens:List[int]=[kforkinm_listifk%2==0]If you want to something to happen just if aMaybemonad is definedforninJust("one"):...The same apply forResults