【发布时间】:2020-11-16 00:21:47
【问题描述】:
当我读到提升的概念时,它是这样实现的(在 Javascript 中)
const liftA2 = f => (a, b) => b.ap(a.map(f));
我意识到liftA2 会产生错误的情况:当b 是Right/Just 和a 是Left/Nothing,因为映射一个@当我们需要它成为部分应用的函数时,987654332@/Nothing 不会对值做任何事情。
当a 和b 都是Left 时,它不会爆炸,但当然返回的Left 的值将是b 的值,我想这可能是问题取决于您的期望。
提升与这些类型一起使用的功能是否是一回事?在使用这样的功能之前,我是否应该系统地明确地防范这些情况?上述实现是否正确/完整?
您将在下面找到有关该问题的更多详细信息
让我们定义函数来提升const add = a => b => a + b;在基本的
Wrapper实现of、ap和map的情况下,我们可以跟踪正在发生的事情class Wrapper { constructor(value) { this.value = value; } static of(value) { return new Wrapper(value); } map(f) { return Wrapper.of(f(this.value)); } ap(a) { return this.map(a.value); } } const a = Wrapper.of(1); const b = Wrapper.of(2); // liftA2 const tmp = a.map(add); // Wrapper { λ } b.ap(tmp); // Wrapper { 3 }但
Either或Maybe的问题在于,他们有Left/Nothing的情况,其中map和ap是打算 什么都不做 p>class Left { constructor(value) { this.value = value; } static of(value) { return new Left(value); } map(f) { return this; } ap(a) { return this; } } class Right{ constructor(value) { this.value = value; } static of(value) { return new Right(value); } map(f) { return Right.of(f(this.value)); } ap(a) { return this.map(a.value); } } const a = Left.of(1); const b = Right.of(2); // liftA2 const tmp = a.map(add); // Left { 1 } b.ap(tmp); // Error because tmp's value is not a function
【问题讨论】:
-
您的示例代码的问题是
Right.prototype.ap已损坏。它需要将a参数区分为Left和Right,它不能只访问它的.value。 -
@geoffrey 好吧,它不能返回预期输出类型的
Right,因为没有构造一个值,所以它 has to 返回Left值.在这种特殊情况下,它基本上由 monad 接口指定。 -
@geoffrey "连 Right 都应该知道 Left 类型吗?" - 它们不是独立的、不同的类型,它们根本不是类型。它们是同一类型的值构造函数:
Either。是的,任何Either方法都需要知道Left和Right。在这方面,您使用两个classes 的实现有点奇怪。当然你可以用动态调度来模拟模式匹配,但是ap需要做两次。 -
@geoffrey learnyouahaskell.com/chapters
-
@geoffrey Shameless plug:我更新了我课程中type theory 的章节。它仍然需要修正错字等,但它是可读的。如果您仍然感兴趣..
标签: functional-programming lifting