首页 文章

JS Monad单元功能

提问于
浏览
16

我'm struggling with understanding the unit function in JavaScript. Particularly because the thing that made me '得到'monads(或者至少我认为)是Promise对象,以及 then 总是返回一个新的Promise,无论你传递给 then 的函数是什么,据我所知,这相当于haskell中的 bind>>= . 这对我来说完全有意义,因为它可以确保所有函数都在_3033189中执行,可以这么说 .

什么's tripping me up is the ' Monads和Gonads的谈话由道格拉斯克罗克福德 . 在他的实现中, bind 直接返回转换函数的结果,而不检查结果本身是否为monad . 这与Promises的 then 方法冲突,因为 then 总是返回一个新的Promise .

一种想法是提升方法 . 他的实施确保'lift'将永远返回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);  
}

我的麻烦区

// 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);
}

注意我知道我特别关注绑定方法 .

完整的实施可以在

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

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

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

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

1 回答

  • 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定义 .

    关于方法的几点说法:

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

    在幻想土地规范中,这是 of() 功能/方法 .

    • 第二个是重要的,因为Haskell使用monad的定义 unitbind 而其他( fmapjoin )是从它们推断出来的 .

    Haskell的 bind 在幻想土地规范中被命名为 chain 因为 bind 在JavaScript中被 Function.prototype 藐视,所以有人认为 chain 足够接近 .

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

    • Haskell的 then

    仅仅是方便

    当第二个动作不涉及第一个动作的结果时,对两个monadic动作进行排序,这对于像IO这样的monad是常见的 .

    在实践中:

    • 它可能会让你厌倦JS,因为没有严格的类型强制执行,你总是不能遵循规则并从 Promise 中返回你想要的任何内容,例如,从而打破了所述承诺的链条 .then() .

    • jQuery 这样的一些monad具有"lifted"函数作为始终返回 jQuery 的方法,即具有相同类型的"protecting"链的能力 .

相关问题