Попытка понять, возможно, Монады, используя LiveScript
Я пытаюсь понять монады лучше. Это минимальная реализация Правильного Монады?
Maybe = (value) ->
@value = value
Maybe.prototype.ret = -> @value
Maybe.prototype.bind = (fn) ->
if not (@value is null)
return fn @value
@value
Maybe.prototype.lift = (fn) -> (val) -> new Maybe fn val
Также, если это правильно - есть заключительная функция, которую я не понимаю, как обобщать.
Maybe.prototype.lift2 = (fn) -> (M1, M2) ->
f = M1.bind ((val1) -> M2.bind (val2) -> fn val1, val2)
new Maybe f
Теперь, как вы обобщаете это для lift3,lift4.... liftn Источник: http://modernjavascript.blogspot.co.uk/2013/06/monads-in-plain-javascript.html
Контрольный вопрос:
Не могли бы вы дать мне простой пример того, как объединить Maybe Monad с другой Monad для простоты, давайте сделаем Обещание с .then
метод
Так как настоящая полезность монад преобразует их.
1 ответ
Это один из способов реализации Maybe
монада в LiveScript:
class Maybe
({x}:hasValue?) ->
# map :: [Maybe a -> ] (a -> b) -> Maybe b
@map = (f) ->
if !hasValue then Nothing else Just (f x)
# bind :: [Maybe a -> ] (a -> Maybe b) -> Maybe b
@bind = (f) ->
if !hasValue then Nothing else f(x)
# toString :: [Maybe a -> ] String
# note here it's not necessary for toString() to be a function
# because Maybe is can only have either one these values:
# Nothing or Just x
@show =
if !hasValue then 'Nothing' else "Just #{x.toString!}"
# static method
@pure = (x) -> Just x
Конструктор принимает оптинал {x}
параметр. Maybe
В Haskell реализовано сопоставление с образцом по его значению-константерам. Этот забавный параметр является хакерским, потому что JavaScript (LiveScript) не поддерживает SumTypes.
Теперь мы можем определить Just
а также Nothing
как:
# Just :: x -> Maybe x
Just = (x) -> new Maybe {x}
# Nothing :: Maybe x
Nothing = new Maybe null
Чтобы проверить наше "Возможно", давайте определим safeSqrt
функция:
# safeSqrt :: Number -> Maybe Number
safeSqrt = (x) ->
if x > 0 then Just (Math.sqrt x) else Nothing
# operation :: Maybe Number
operation = do ->
a = Just 4
.map (x) -> x * -16
.bind safeSqrt
console.log operation.show
Этот код напечатает Nothing
,
liftM2
это функция, которая действует на любую монаду. Он должен знать тип базовой монады, потому что он использует pure
(что в нашей реализации является статической функцией):
# liftM2 :: Monad m => (a -> b -> c) -> m a -> m b -> m c
liftM2 = (monadType, f, m1, m2) -->
x1 <- m1.bind
x2 <- m2.bind
monadType.pure (f x1, x2)
Вот как мы можем использовать это:
# operation :: Maybe Number
operation = do ->
a = Just 4
.map (x) -> x * 16
.bind safeSqrt
b = safeSqrt 81
liftM2 Maybe, (+), a, b
console.log operation.show