javascript - 尝试使用 LiveScript 理解 Maybe Monad

标签 javascript monads option-type livescript

我正在尝试更好地理解单子(monad)。 这是 Maybe Monad 的最小实现正确吗?

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 方法将其保留为 Promise

因为 Monad 的真正用处是改变它们。

最佳答案

这是在 LiveScript 中实现 Maybe monad 的一种方法:

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}参数。 Haskell 中的 Maybe 是通过对其值构造函数进行模式匹配来实现的。这个有趣的参数是对其的一种破解,因为 JavaScript (LiveScript) 不支持 SumTypes。

现在我们可以将 JustNothing 定义为:

# Just :: x -> Maybe x
Just = (x) -> new Maybe {x}

# Nothing :: Maybe x
Nothing = new Maybe null

为了测试我们的 Maybe,让我们定义一个 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 是一个可以在任何 monad 上运行的函数。它需要知道底层 monad 的类型,因为它使用 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

Code in JSBin

关于javascript - 尝试使用 LiveScript 理解 Maybe Monad,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37581139/

相关文章:

javascript - 抽象状态如何在 Ionic 中工作?

javascript - 为什么具有精确值的 float 之和仍然取决于顺序?

javascript - CryptoJs 无法解密我的 NodeJS 服务器上的 URL

haskell - 为什么 "bind"在 Haskell Monads 中写为 >>=?

java - Haskell 中的 undefined 和 Java 中的 null 有什么区别?

javascript - 如何在 AngularJS 中保存所选选项(下拉框)

haskell - IO monad 在什么意义上是特殊的(如果有的话)?

haskell - 为什么 Haskell 中的 `forever` 是这样实现的?

swift - 核心数据 Int16 作为可选

ios - 如何使用 NSObject 属性