为什么 fantasy land 规范要求链必须 return 同一个链的值?
Why does the fantasy land spec require that chain must return a value of the same Chain?
chain
method
A value which has a Chain must provide a chain
method. The chain
method takes one argument:
m.chain(f)
f
must be a function which returns a value
- If
f
is not a function, the behaviour of chain
is unspecified.
f
must return a value of the same Chain
chain
must return a value of the same Chain
给定的是选项 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
总是 returns 一个选项 monad,我必须确保 mf
(monadic 函数)总是 returns 一个。这是不可能的,因为 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!
在第二种方法中,传递的函数 returns 没有 monad,这导致 monadic 计算的解包结果。我可以向 chain
或 join
添加类型检查,也许可以通过 duck typing 来解决这个问题——虽然这会很丑陋。
为什么规范恰恰在此时要求类型安全? Javascript 是动态类型的,我更愿意编写适当的单元测试而不是在 运行 时执行类型检查。那我会违反规范吗?
在你的第二个例子中你应该使用 .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()
因此,如果您的函数 returns 是一元值,请使用 .chain()
。否则使用 .map()
.
chain
methodA value which has a Chain must provide a
chain
method. The chain method takes one argument:
m.chain(f)
f
must be a function which returns a value
- If
f
is not a function, the behaviour ofchain
is unspecified.f
must return a value of the same Chainchain
must return a value of the same Chain
给定的是选项 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
总是 returns 一个选项 monad,我必须确保 mf
(monadic 函数)总是 returns 一个。这是不可能的,因为 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!
在第二种方法中,传递的函数 returns 没有 monad,这导致 monadic 计算的解包结果。我可以向 chain
或 join
添加类型检查,也许可以通过 duck typing 来解决这个问题——虽然这会很丑陋。
为什么规范恰恰在此时要求类型安全? Javascript 是动态类型的,我更愿意编写适当的单元测试而不是在 运行 时执行类型检查。那我会违反规范吗?
在你的第二个例子中你应该使用 .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()
因此,如果您的函数 returns 是一元值,请使用 .chain()
。否则使用 .map()
.