=>(import [hymn.types.either[LeftRighteitherfailsafe]])=>(require[hymn.macros[do-monad]])=>;; do notation with either monad=>(do-monad[a(Right1)b(Right2)](/ ab))Right(0.5)=>(do-monad[a(Right1)b(Left'nan)](/ ab))Left(HySymbol('nan'))=>;; failsafe is a function decorator that wraps return value into either=>(setvsafe-div(failsafe/))=>;; returns Right if nothing wrong=>(safe-div42)Right(2.0)=>;; returns Left when bad thing happened, like exception being thrown=>(safe-div10)Left(ZeroDivisionError('divisionbyzero',))=>;; function either tests the value and calls functions accordingly=>(eitherprint inc (safe-div42))3.0=>(eitherprint inc (safe-div10))divisionbyzero

The identity monad

=>(import [hymn.types.identity[identity-m]])=>(require[hymn.macros[do-monad]])=>;; do notation with identity monad is like let binding=>(do-monad[a(identity-m1)b(identity-m2)](+ ab))Identity(3)

The lazy monad

=>(import [hymn.types.lazy[force]])=>(require[hymn.types.lazy[lazy]])=>;; lazy computation implemented as monad=>;; macro lazy creates deferred computation=>(setva(lazy(print "evaluate a")42))=>;; the computation is deferred, notice the value is shown as '_'=>aLazy(_)=>;; evaluate it=>(.evaluatea)evaluatea42=>;; now the value is cached=>aLazy(42)=>;; calling evaluate again will not trigger the computation=>(.evaluatea)42=>(setvb(lazy(print "evaluate b")21))=>bLazy(_)=>;; force evaluate the computation, same as calling .evaluate on the monad=>(forceb)evaluateb21=>;; force on values other than lazy return the value unchanged=>(force42)42=>(require[hymn.macros[do-monad]])=>;; do notation with lazy monad=>(setvc(do-monad[x(lazy(print "get x")1)y(lazy(print "get y")2)](+ xy)))=>;; the computation is deferred=>cLazy(_)=>;; do it!=>(forcec)get xget y3=>;; again=>(forcec)3

=>(import [hymn.types.reader[lookup]])=>(require[hymn.macros[do-monad]])=>;; do notation with reader monad, lookup assumes the environment is subscriptable=>(setvr(do-monad[a(lookup'a)b(lookup'b)](+ ab)))=>;; run reader monad r with environment=>(.runr{'a1'b2})3

The state monad

=>(import [hymn.types.state[lookupset-value]])=>(require[hymn.macros[do-monad]])=>;; do notation with state monad, set-value sets the value with key in the state=>(setvs(do-monad[a(lookup'a)_(set-value'b(inc a))]a))=>;; run state monad s with initial state=>(.runs{'a1})(1, {HySymbol('a'):1, HySymbol('b'):2})