组成诺言和自定义单子

时间:2019-02-16 14:05:40

标签: javascript functional-programming

上下文

我正在尝试理解monades试图解决的问题,在尝试构建容器和Promise时我有些困惑。

示例

出于练习的目的,我将monad的chain方法修改为then,以便可以使用自定义容器编写promises。

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世界中。

问题

  • 我现在想知道我在工作并尝试编写monade时是否必须解除所有内容(甚至是诺言?)?

  • 如果我使用10种不同的monade有什么影响?我的意思是,根据订单,我可能会改变我正在努力的世界吗?

  • 这对于创建monades创造者来说很常见吗?我的意思是像创建的makeMonad一样创建monade定义

感谢您的帮助,我希望我很清楚^^'

1 个答案:

答案 0 :(得分:0)

  

我正在尝试理解monades试图解决的问题

查看此仓库中的示例和参考资料可能会有所帮助 https://github.com/dmitriz/functional-examples

  

尝试组成一个容器和一个Promise时,我有些困惑。

我想您知道the Promise is not a Monad

  

出于该练习的目的,我将monad的chain方法修改为then,以便可以使用自定义容器编写promises

作为then方法breaks Monadic law, 它不适合安全成分。基本上,每次使用函数编写时,都必须仔细检查所有可能的返回值是否为承诺值,并确保始终正确地解开该组合。从根本上来说,这与Monad的观点相违背,Monad使您可以安全地进行撰写而无需花费时间进行详细检查。如果利用Monads是您的目标,则您可能希望从then切换到chain

一个{@ 3}}


  
      
  • 我现在想知道在工作和尝试编写monade时是否必须取消所有内容(甚至是诺言?)?
  •   

您可能希望将所有的Promise包裹在creed中,然后以通常的方式使用提供的monadic方法。

  
      
  • 如果我使用10种不同的monade,会有什么影响?我的意思是,根据订单,我可能会改变我正在努力的世界吗?
  •   

一元法则适用于固定的monad,即它们仅适用于ofchain方法的固定实现。另外chain期望正确的签名:

chain :: Monad m => m a ~> (a -> m b) -> m b

解密:如果m是固定的Monad,ab是任何类型,则chain方法要求其参数为a → m b类型的函数,且m同一单子

换句话说

monad.chain(a => makeMonad(a))

假定函数makeMonad构成相同的单子。否则,只要使用chain,就需要将结果包装到正确的monad中。

要使它与诺言一起安全地工作,请始终将其包装到Creed中以确保使用相同的monad,然后仅在构成和依赖于monadic法则时才使用mapchain。或使用then冒着风险,担心细节:)

  
      
  • 这对于创建monades创造者来说是常见的吗?我的意思是像我编写的makeMonad一样创建monade定义
  •   

这仅在您具有实际值开始时才起作用,请参见例如此处:Creed

但是Monad的功能之一就是处理您无法(或不想)直接访问的值,例如IO Monad。在这些情况下,您只能使用提供的运算符来创建或不可以创建Monad。这说明了原生JS Promise的问题-在不更改其值的情况下,您无法以任何方式使它们成为Monad。原生JS承诺会始终尝试解开“ theneable”,因此无法将其存储为值,从而使任何合成通常都不安全。