javascript - Trying to understand Maybe Monads using LiveScript -
i trying understand monads better. minimal implementation of maybe monad correct ?
maybe = (value) -> @value = value maybe.prototype.ret = -> @value maybe.prototype.bind = (fn) -> if not (@value null) return fn @value @value maybe.prototype.lift = (fn) -> (val) -> new maybe fn val
also if correct - there final function confused how generalize.
maybe.prototype.lift2 = (fn) -> (m1, m2) -> f = m1.bind ((val1) -> m2.bind (val2) -> fn val1, val2) new maybe f
now how generalize lift3,lift4.... liftn source : http://modernjavascript.blogspot.co.uk/2013/06/monads-in-plain-javascript.html
follow question:
could give me simple example of how combine maybe monad monad simplicity sake lets keep promise .then
method
since real usefulness of monads transforming them.
this 1 way of implementing maybe
monad in livescript:
class maybe ({x}:hasvalue?) -> # map :: [maybe -> ] (a -> b) -> maybe b @map = (f) -> if !hasvalue nothing else (f x) # bind :: [maybe -> ] (a -> maybe b) -> maybe b @bind = (f) -> if !hasvalue nothing else f(x) # tostring :: [maybe -> ] string # note here it's not necessary tostring() function # because maybe can have either 1 these values: # nothing or x @show = if !hasvalue 'nothing' else "just #{x.tostring!}" # static method @pure = (x) -> x
the constructor takes optinal {x}
parameter. maybe
in haskell implemented pattern matching on value consturctors. funny parameter hack around it, because javascript (livescript) doesn't support sumtypes.
now can define just
, nothing
as:
# :: x -> maybe x = (x) -> new maybe {x} # nothing :: maybe x nothing = new maybe null
to test our maybe, let's define safesqrt
function:
# safesqrt :: number -> maybe number safesqrt = (x) -> if x > 0 (math.sqrt x) else nothing # operation :: maybe number operation = -> = 4 .map (x) -> x * -16 .bind safesqrt console.log operation.show
this code print nothing
.
liftm2
function operates on monad. needs know type of underlying monad, because uses pure
(that in our implementation static function):
# liftm2 :: monad m => (a -> b -> c) -> m -> m b -> m c liftm2 = (monadtype, f, m1, m2) --> x1 <- m1.bind x2 <- m2.bind monadtype.pure (f x1, x2)
here's how can use it:
# operation :: maybe number operation = -> = 4 .map (x) -> x * 16 .bind safesqrt b = safesqrt 81 liftm2 maybe, (+), a, b console.log operation.show