2

chain方法

具有 Chain 的值必须提供chain方法。chain 方法接受一个参数:

m.chain(f)

  1. f必须是返回值的函数
    • 如果f不是函数,则 的行为chain未指定。
    • f必须返回相同链的值
  2. chain必须返回相同链的值

GitHub - 幻想世界

Given 是选项 monad 的简单实现:

// prototypes:
const someProto = {
  of(x) { return some(x) },
  map(f) { return some(f(this.x)) },
  ap(ftor) { return ftor.map(this.x) },
  join() { return this.x },
  chain(mf) { return this.map(mf).join() }
};

const noneProto = {
  of() { return this },
  map() { return this },
  ap() { return this },
  join() { return this },
  chain() { return this }
};

// factories:
function some(x) {
  return Object.assign(Object.create(someProto), {x: x});
}

function none() {
  return Object.assign(Object.create(noneProto), {x: null});
}

为了保证chain总是返回一个选项单子,我必须确保mf(monadic function) 总是返回一个。这是不可能的,因为mf它不是实现的一部分。相反,它是在使用 monad 时定义的:

// auxiliary function:
const sub = y => x => x - y;

let a = some(2);
let b = some(3);

a.chain(x => b.chain(y => some(sub(x)(y)))); // {x: 1}
a.chain(x => b.chain(y => sub(x)(y))); // 1 - ouch!

在第二个方法应用程序中,传递的函数不返回单子,这导致单子计算的展开结果。我可以添加一个类型检查,chain或者join通过鸭子打字来解决这个问题——虽然这会很丑陋。

为什么规范在这一点上要求类型安全?Javascript 是动态类型的,我更愿意编写适当的单元测试,而不是在运行时执行类型检查。那我会违反规范吗?

4

1 回答 1

1

在第二个示例中,您应该使用.map()

a.chain(x => b.map(y => sub(x)(y))); 

然后一切都遵循规则。

为了比较,这里是等效的 Haskell 签名:

fmap  :: m a -> (a ->   b)   -> m b    -- same as .map()
(>>=) :: m a -> (a -> m b)   -> m b    -- same as .chain()

因此,如果您的函数返回一个单子值,请使用.chain(). 否则使用.map().

于 2016-06-11T18:35:57.520 回答