我试图了解ap
,但遇到了麻烦。
在fantasyland中,詹姆斯福布斯说:
首先,我们通过将该函数存储在容器中来教授函数如何与我们的类型进行交互,就像任何其他值一样。 (功能也是值得知道的!)
var square = Type.of(
a => a * a
)
//=> Type (number -> number)
然后我们可以将包含的函数应用于包含的值。
square.ap( Type.of(3) )
//=> Type(9)
ap
对收到的类型调用map
,并将自身作为转换函数。
function ap(type){
// recall our value
// is a function
// Type ( a -> a )
var transformer = this.__value
return type.map(transformer)
}
所以这看起来像ap
只有在容器中的值是函数时才有效。这对我来说已经很奇怪,因为我认为The Perfect API的重点在于这些功能每次都适用于所有事情。
我还想注意,而不是因为square.ap(Type.of(3) )
行,我认为ap
需要任何仿函数(map
的实现者)。
现在,如果我跳转到javascript fantasy-land spec,我假设它基于James Forbes链接,ap
签名(a.ap(b)
)的1.i定义指出
如果
b
不代表某个函数,则ap
的行为未指定。
所以听起来这个规范期望ap
采用与完美API不同的功能。
总之,我想我不理解ap
的规范或实现它的样子。当我尝试谷歌搜索时,似乎大多数人只想谈论map
,这对我来说很容易理解。
答案 0 :(得分:1)
FantasyLand规范早于詹姆斯福布斯'文章三年,由Brian McKenna创作,所以看起来詹姆斯福布斯'文章是基于规范,而不是相反。
要回答您的问题,a
和b
必须是同一种"容器"。如果a
是一个可能,那么b也必须是一个可能。如果a
是任务,则b
也必须是任务。
这在FantasyLand规范中有说明:
b必须相同适用于。
此外,其中一个必须包含一个函数作为其内部值。哪一个需要包含一个函数取决于API。在FantasyLand规范中,它包含了b
函数:
b必须是函数的应用
詹姆斯福布斯'文章,它恰恰相反。我怀疑这是因为他的文章基于Ramda,它的参数与你在JavaScript中通常看到的相反。
在任何情况下,ap
的结果都是与a
和b
具有相同类型容器的值:
ap返回的Apply必须与a和b
相同
,结果包含将包含的函数应用于其他包含值的结果。
因此,如果a
为某个值T [x]且b
为某个值T [f],那么a.ap(b)
将为T[f(x)]
。
希望这是有道理的。