JS Monad单位函数

时间:2016-03-19 08:15:43

标签: javascript functional-programming monads

我正在努力理解JavaScript中的单元函数。特别是因为让我'得到'monad(或至少我认为)的东西是Promise对象,以及then如何总是返回一个新的Promise,无论你传递给then的函数是什么,据我所知,相当于haskell中的bind>>=。这对我来说是完全有意义的,因为它确保你所有的功能都在'monad universe'中执行,可以这么说。

道格拉斯·克罗克福德(Douglas Crockford)的“Monads and Gonads”演讲让我感到震惊。在他的实现中,bind直接返回转换函数的结果,而不检查结果本身是否为monad。这与Promises的then方法冲突,因为then总是返回一个新的Promise。

一种想法是提升方法。他的实施确保'升力'将永远返回monad,并且可能then被提升到Promise。但是,这意味着then !== bind,并且Promise在某处具有内部绑定。

我的直觉是,在绑定函数中至少应该进行某种类型的检查,检查转换的结果,并允许生成的monad通过,但是会截取非monad并将它们传递给unit再次,就像'升力'一样。

*编辑
另外,我认为then相当于bind, flatMap, >>=,因为它有能力打开其他monad,包括不同的monad和它自己的类型。在查看JavaScript中的某些类别理论引用时,flatMap用于映射一组嵌套数组,然后将它们展平为一维。这符合then等待你提供的其他承诺的方式。但似乎与上面提到的原始实现不匹配。我感到迷茫。

任何拥有更多FP经验的人都会对我所缺少的东西有所了解,或者我是否太过分了,需要从头开始?

一些代码示例......

// Crockford's 'bind'
monad.bind = function(transform) {
  // value was passed in through the unit constructor
  return transform(value);  
}

我的麻烦区域

// Set the 'isMonad' prop to be true, for all
// monads made with the MONAD macroid
monad.isMonad = true;

// shouldn't this ALWAYS return a monad?
monad.bind = function(transform) {
  var res = transform(value);
  return ( res && res.isMonad ) ? res : unit(res);
}

注意我知道我没有完全使用他的实现的最终版本,我只是特别关注bind方法。

完整的实施可以在

找到

https://github.com/douglascrockford/monad/blob/master/monad.js

更新

在做了一些研究后,>>=不需要返回Monad实例。 Bergi的评论阐明了Promise.prototype.then如何被重载,并根据你解决它的方式起到不同的作用。

此外,当我退后一步,看看Monads与常规仿函数有何不同时,很多东西都开始点击了。细节仍然有点模糊,但我认为我得到了全局。

一些有助于清除阴霾的好参考资料,

强烈推荐这个词用于高级概述,用人类的话来说 http://adit.io/posts/2013-04-17-functors,_applicatives,_and_monads_in_pictures.html
不要让图片欺骗你,这对我来说就像金子一样。不是在JavaScript中,但在整体概念方面仍然非常有用。

此外,这个关于JavaScript类别理论的YouTube系列 https://www.youtube.com/watch?v=-FkgOHvNAU8&list=PLwuUlC2HlHGe7vmItFmrdBLn6p0AS8ALX&index=1

这个名为“Fun Fun Function”的YouTube系列很精彩,主持人是我在网上找到的最好的老师之一。此视频是关于monad的,由MrE建议 强烈推荐!。

https://www.youtube.com/watch?v=9QveBbn7t_c&app=desktop

这两个参考文献特别为我创造了奇迹。希望能帮助其他人。

1 个答案:

答案 0 :(得分:1)

我不太明白你的问题,但我会假设:

  

Monad的正确定义是什么,就JS而言,它是两种方法?

Haskell 术语中(取自https://en.wikibooks.org/wiki/Haskell/Understanding_monads),这很简单:

    return :: a -> m a
    (>>=)  :: m a -> (a -> m b) -> m b

    (>>)   :: m a -> m b -> m b

对于 JavaScript 术语,请不要再看了,简短的答案就在这里https://github.com/fantasyland/fantasy-land#monad 以及其他连接的FP定义。

方法上几句话:

  1. 有一点是unit Haskell 中的return)必须产生一个monad(不是精确的monad,但是为了参数...),因为它就像一个构造函数,它将一个值放在容器中。 Array.of()就是一个例子,jQuery()是另一个例子,当然也是new Promise()

    Fantasy Land Specification 中,这是of()函数/方法。

  2. 第二个很重要,因为 Haskell 使用了unitbind的monad定义,而其他人fmap,{{1从它们推断形成它们。

    Haskell的 join幻想土地规范中被命名为bind,因为chainbind上被视为Function.prototype JavaScript 中,有人认为chain足够接近。

    bindchain“必须”返回同一类型的monad的原因是因为 (>>=) :: m a -> (a -> m b) -> m b。简而言之, Haskell的 bind函数必须只接受一个返回monad的函数(这部分a -> m b),所以你得到它的结果。

  3. Haskell的 then

      

    仅仅是方便

      当第二个动作不涉及第一个动作的结果时,

    对两个monadic动作进行排序,这对于像IO这样的monad是常见的。

  4. 在实践中:

    1. 它可能会让你厌倦JS,因为没有严格的类型强制执行,你总是不能遵循规则并从Promise返回你想要的任何东西,例如,因此打破了{{ 1}}所述承诺链。

    2. .then()这样的一些monad已经“提升”了一些函数,它们总是返回jQuery即相同类型的方法,从而“保护”链的能力。