javascript - JS Monad 单元函数

标签 javascript functional-programming monads

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

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

一个想法是提升方法。他的实现确实确保“提升”将始终返回一个 monad,并且可能 then 被提升到 Promise。然而,这意味着 then !== bind,并且 Promise 在某处有一个内部绑定(bind)。

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

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

任何有更多 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 是如何重载的,并根据您使用的解析方式充当不同的函数。

此外,当我退后一步并查看 Monad 与常规仿函数的不同之处时,很多事情开始变得清晰起来。细节仍然有点模糊,但我想我明白了大局。

一些有助于消除阴霾的好引用,

强烈推荐使用人类语言进行高级概述
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

这两个引用文献特别为我创造了奇迹。希望对其他人也有帮助。

最佳答案

我不太明白你的问题是什么,但我假设是这样的:

what is the correct definition of a Monad and it's two methods in terms of 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 规范中,这是 of() 函数/方法。

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

    Haskell 的 bindFantasy Land Specification 中被命名为 chain 因为bindJavaScript 中违反了 Function.prototype,因此有人认为 chain 足够接近。

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

  3. Haskell 的 then

    is a mere convenience

    sequences two monadic actions when the second action does not involve the result of the first, which is common for monads like IO.

实践中:

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

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

关于javascript - JS Monad 单元函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36099475/

相关文章:

javascript - 映射并返回已解决的 promise 数组的函数的名称?

haskell - 了解 >>= 中的 "Monad m"

haskell - 为什么 Haskell 中没有 `Cofunctor` 类型类?

javascript - rails 4 : Passing a variable from controller to javascript

javascript - 如何等待$.getJSON()?

javascript - 在 PhantomJS 和 Python 中伪造 Flash 插件信息

javascript - 一种更惯用的方式来编写庇护管道

java - 这是 Clojure 中可变状态的明智单子(monad)吗?

javascript - 有底部限制的粘性左侧部分

Scala 尝试和奇怪的行为