javascript - 编写 promise 和自定义 monad
问题描述
语境
我试图理解 monades 试图解决的问题,在尝试编写容器和承诺时我有点困惑。
例子
出于练习的目的,我将chain
monad 的方法修改为 a then
,以便可以使用自定义容器编写 Promise:
const assert = require("assert");
const R = require("ramda");
const makeMonad = value => ({
get: () => value,
map: transform => makeMonad(transform(value)),
then: createMonad => makeMonad(createMonad(value).get())
});
const asyncAdd2 = x => Promise.resolve(x + 2);
const composeP = R.composeWith((f, last) => last.then(f));
const asyncResult = composeP([asyncAdd2, makeMonad])(1);
asyncResult.then(x => assert.equal(x, 3));
console.log("Passed");
在此示例中,我抛出了一个错误,因为Promise
API 不拥有get
函数。事实上,我需要get
在我的自定义then
函数中使用这个函数来实现可组合性。
因此,在应用程序执行结束时,根据我在composeWith
调用中的参数顺序,我处于 Promise 世界或自定义 monad 世界。
问题
我现在想知道在我工作并尝试编写单子时是否必须举起一切(甚至是承诺?)?
如果我使用 10 种不同的单子会有什么影响?我的意思是,根据顺序,我可能会改变我正在努力的世界,不是吗?
这是创建 monades 创造者的共同点吗?
makeMonad
我的意思是像我写的那样创建单子定义
感谢您的帮助,我希望我已经清楚了^^'
解决方案
我试图理解 monades 试图解决的问题
查看此 repo https://github.com/dmitriz/functional-examples中的示例和参考资料可能会对您有所帮助
在尝试编写容器和承诺时,我有点困惑。
我想你知道Promise 不是 Monad。
出于练习的目的,我已将我的 monad 的 chain 方法修改为 a
then
,以便我可以使用我的自定义容器编写 Promise
由于then
方法违反一元法则,不适合安全合成。基本上每次你用函数组合时,你必须仔细检查所有可能的返回值是否是承诺,并确保组合总是正确解包。这基本上违背了 Monad 的观点,即允许您安全地进行创作而无需花费时间进行细节检查。如果利用 Monads 是您的目标,您可能更愿意从 to 切换then
到chain
。
Creed是一个为 Promises 带来 FP 安全性的优秀库
- 我现在想知道在我工作并尝试编写单子时是否必须举起一切(甚至是承诺?)?
您可能希望将所有 Promise 包装进去creed
,然后以通常的方式使用提供的 monadic 方法。
- 如果我使用 10 种不同的单子会有什么影响?我的意思是,根据顺序,我可能会改变我正在努力的世界,不是吗?
单子法则适用于固定的单子,即它们仅适用于of
andchain
方法的固定实现。还chain
期望正确的签名:
chain :: Monad m => m a ~> (a -> m b) -> m b
Decrypted:如果m
是一个固定的 Monad,a
并且b
是任何类型,chain 方法要求它的参数是 type 的函数a → m b
,并且m
是同一个 monad。
换句话说
monad.chain(a => makeMonad(a))
假定功能makeMonad
是制作相同的 monad。否则,无论何时使用,您都需要将结果包装到正确的 monadchain
中。
为了使它与 Promise 一起安全工作,总是将它们包装到 Creed 中以保证使用相同的 monad,然后只在编写和依赖 monad 法则时使用map
和。chain
或自then
担风险使用并担心细节:)
- 这是创建 monades 创造者的共同点吗?我的意思是像我写的 makeMonad 一样创建 monade 定义
这仅在您开始具有实际价值时才有效,请参见此处:https ://github.com/dmitriz/functional-examples/blob/master/examples/16-monad.js
但是 Monad 的强大功能之一是处理您不能(或不想)直接访问的值,例如 IO Monad。在这些情况下,您只能使用提供的运算符来可能或可能无法创建 Monad。这说明了原生 JS 承诺的问题——你不能以任何方式将它们变成 Monad 而不改变它们的值。原生 JS 承诺总是会尝试解开“theneable”,因此不能将其存储为值,这使得任何组合通常都是不安全的。
推荐阅读
- php - 为什么有些电子邮件 ID 被接受而有些不是 PHP
- python - 使用返回看不到结果
- android - 字段重叠,以编程方式创建布局
- ruby-on-rails - 通过层次结构获取平均总和
- java - 如何在 JavaDoc 中链接 com.android.Volley 包
- c++ - STL 的头文件
- powershell - 如何在powershell中拆分大于X的文本文件行?
- excel - VBA查找和替换到不同的列,同一行,SKIP IF Cell有一个值
- c# - C#“不能隐式转换类型”相同的模型属性
- node.js - Beanstalk 无法在 npm 启动失败时中止部署