JS Monad单元功能

Dus*_*les 16 javascript monads functional-programming

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

让我振作起来的是Douglas Crockford的"Monads and Gonads"演讲.在他的实现中,bind直接返回transform函数的结果,而不检查结果本身是否为monad.这与Promises的then方法发生冲突,因为thenALWAYS会返回一个新的Promise.

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

我的直觉是,在绑定函数中至少应该进行某种类型的检查,检查转换的结果,并允许生成的monad被允许通过,但是会拦截非monad并再次通过它们,就像'升力'确实如此.

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

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

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

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

我的麻烦区

// 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);
}
Run Code Online (Sandbox Code Playgroud)

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

完整的实施可以在

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系列很精彩,主持人是我在网上找到的最好的老师之一.这个视频是关于monads的,并被提出MrE.
强烈推荐!.

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

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

Azd*_*der 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
Run Code Online (Sandbox Code Playgroud)

对于JavaScript术语,不用再犹豫了,简短的答案在这里https://github.com/fantasyland/fantasy-land#monad 以及其他相关的 FP 定义。

关于方法的几句话:

  1. 一件事是unitreturnHaskell中)必须生成一个 monad(不完全是 monad,而是为了论证......),因为它就像一个将值放入容器中的构造函数。Array.of()这是一个例子,jQuery()也是另一个例子,当然new Promise()也是如此。

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

  2. 第二个很重要,只是因为Haskell使用了 monad 的定义unit,而bind其他的 ( fmap, join) 是从它们推断出来的。

    Haskell在Fantasy Land 规范中被命名,因为它在JavaScript 被拒绝,所以有人认为足够接近。bindchainbindFunction.prototypechain

    bind而ie “必须”返回相同类型的 monad 的原因chain是因为 (>>=) :: m a -> (a -> m b) -> m b. 简而言之,Haskell 的 bind函数必须只接受返回 monad 的函数(这部分a -> m b),这样您就可以得到它的结果。

  3. 哈斯克尔 then

    仅仅是一种方便

    当第二个动作不涉及第一个动作的结果时,对两个单子动作进行排序,这对于像 IO 这样的单子来说很常见。

在实践中:

  1. 在 JS 中,这可能会让你感到厌烦,因为没有严格的类型强制,你总是可以不遵循规则并从 a 返回任何你想要的东西Promise,例如,从而破坏了.then()所说的承诺链。

  2. 一些单子具有“提升”功能作为始终返回相同类型的jQuery方法,从而“保护”链接的能力。jQuery