我正在努力理解 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 定义。
关于方法的几句话:
有一件事是 unit(Haskell 中的return)必须产生一个 monad(不完全是 monad,但为了论证) ...),因为它就像一个将值放入容器中的构造函数。 Array.of() 是一个示例,jQuery() 是另一个示例,当然还有 new Promise()。
在 Fantasy Land 规范中,这是 of() 函数/方法。
第二个很重要,只是因为 Haskell 使用具有 unit 和 bind 的 monad 定义,而其他的( fmap,join) 是从它们推断出来的。
Haskell 的 bind 在 Fantasy Land Specification 中被命名为 chain 因为bind 在 JavaScript 中违反了 Function.prototype,因此有人认为 chain 足够接近。
bind 即 chain “必须”返回相同类型的 monad 的原因是
(>>=)::m a -> (a -> m b) -> m b。简而言之,Haskell 的 bind 函数必须只接受一个返回 monad 的函数(这部分 a -> m b),所以你得到它的结果。
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.
实践中:
在 JS 中可能会让你感到厌烦,因为没有严格的类型强制,你总是可以不遵守规则并从 Promise 返回任何你想要的东西,例如,从而破坏所述 promise 的 .then() 链。
jQuery 等一些 monad 具有“提升”功能,作为始终返回 jQuery 的方法,即相同类型,从而“保护”链接的能力。
关于javascript - JS Monad 单元函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36099475/
我想在一个没有Sass引擎的类中使用Sass颜色函数。我已经在项目中使用了sassgem,所以我认为搭载会像以下一样简单:classRectangleincludeSass::Script::FunctionsdefcolorSass::Script::Color.new([0x82,0x39,0x06])enddefrender#hamlengineexecutedwithcontextofself#sothatwithintemlateicouldcall#%stop{offset:'0%',stop:{color:lighten(color)}}endend更新:参见上面的#re
我正在尝试用ruby中的gsub函数替换字符串中的某些单词,但有时效果很好,在某些情况下会出现此错误?这种格式有什么问题吗NoMethodError(undefinedmethod`gsub!'fornil:NilClass):模型.rbclassTest"replacethisID1",WAY=>"replacethisID2andID3",DELTA=>"replacethisID4"}end另一个模型.rbclassCheck 最佳答案 啊,我找到了!gsub!是一个非常奇怪的方法。首先,它替换了字符串,所以它实际上修改了
我有一些代码在几个不同的位置之一运行:作为具有调试输出的命令行工具,作为不接受任何输出的更大程序的一部分,以及在Rails环境中。有时我需要根据代码的位置对代码进行细微的更改,我意识到以下样式似乎可行:print"Testingnestedfunctionsdefined\n"CLI=trueifCLIdeftest_printprint"CommandLineVersion\n"endelsedeftest_printprint"ReleaseVersion\n"endendtest_print()这导致:TestingnestedfunctionsdefinedCommandLin
我正在尝试用Prawn生成PDF。在我的PDF模板中,我有带单元格的表格。在其中一个单元格中,我有一个电子邮件地址:cell_email=pdf.make_cell(:content=>booking.user_email,:border_width=>0)我想让电子邮件链接到“mailto”链接。我知道我可以这样链接:pdf.formatted_text([{:text=>booking.user_email,:link=>"mailto:#{booking.user_email}"}])但是将这两行组合起来(将格式化文本作为内容)不起作用:cell_email=pdf.make_c
如何在Ruby中按名称传递函数?(我使用Ruby才几个小时,所以我还在想办法。)nums=[1,2,3,4]#Thisworks,butismoreverbosethanI'dlikenums.eachdo|i|putsiend#InJS,Icouldjustdosomethinglike:#nums.forEach(console.log)#InF#,itwouldbesomethinglike:#List.iternums(printf"%A")#InRuby,IwishIcoulddosomethinglike:nums.eachputs在Ruby中能不能做到类似的简洁?我可以只
说在前面这部分我本来是合为一篇来写的,因为目的是一样的,都是通过独立按键来控制LED闪灭本质上是起到开关的作用,即调用函数和中断函数。但是写一篇太累了,我还是决定分为两篇写,这篇是调用函数篇。在本篇中你主要看到这些东西!!!1.调用函数的方法(主要讲语法和格式)2.独立按键如何控制LED亮灭3.程序中的一些细节(软件消抖等)1.调用函数的方法思路还是比较清晰地,就是通过按下按键来控制LED闪灭,即每按下一次,LED取反一次。重要的是,把按键与LED联系在一起。我打算用K1来作为开关,看了一下开发板原理图,K1连接的是单片机的P31口,当按下K1时,P31是与GND相连的,也就是说,当我按下去时
我需要一个通过输入字符串进行计算的方法,像这样function="(a/b)*100"a=25b=50function.something>>50有什么方法吗? 最佳答案 您可以使用instance_eval:function="(a/b)*100"a=25.0b=50instance_evalfunction#=>50.0请注意,使用eval本质上是不安全的,尤其是当您使用外部输入时,因为它可能包含注入(inject)的恶意代码。另请注意,a设置为25.0而不是25,因为如果它是整数a/b将导致0(整数)。
我对单元测试还是比较陌生。我用Ruby编写了一个类,它接受一个文件,在该文件中搜索给定的Regex模式,替换它,然后将更改保存回文件。我希望能够为此方法编写单元测试,但我不知道我将如何去做。有人能告诉我我们如何对处理文件i/o的方法进行单元测试吗? 最佳答案 看看这个HowdoIunit-testsavingfiletothedisk?基本上这个想法是一样的,文件系统是你的类的依赖。所以引入一个可以在你的单元测试中模拟的角色/接口(interface)(这样你在单元测试时就没有依赖性);角色中的方法应该是您从文件系统中需要的所有东西
我遇到了一个非常奇怪的问题,我很难解决。在我看来,我有一个与data-remote="true"和data-method="delete"的链接。当我单击该链接时,我可以看到对我的Rails服务器的DELETE请求。返回的JS代码会更改此链接的属性,其中包括href和data-method。再次单击此链接后,我的服务器收到了对新href的请求,但使用的是旧的data-method,即使我已将其从DELETE到POST(它仍然发送一个DELETE请求)。但是,如果我刷新页面,HTML与"new"HTML相同(随返回的JS发生变化),但它实际上发送了正确的请求类型。这就是这个问题令我困惑的
我需要从json记录中获取一些值并像下面这样提取curr_json_doc['title']['genre'].map{|s|s['name']}.join(',')但对于某些记录,curr_json_doc['title']['genre']可以为空。所以我想对map和join()使用try函数。我试过如下curr_json_doc['title']['genre'].try(:map,{|s|s['name']}).try(:join,(','))但是没用。 最佳答案 你没有正确传递block。block被传递给参数括号外的方法