Prelude中Bind
类的定义是:
class Apply m <= Bind m where
bind :: forall a b. m a -> (a -> m b) -> m b
它可以作为一个函数读取两个输入参数,monadic上下文中的值(m a
)和函数(a -> m b
)并返回一个值monadic context(m b
)。
部分应用函数的Bind
实例定义为:
instance bindFn :: Bind ((->) r) where
bind m f x = f (m x) x
这是一个采用三个参数的函数。那个类型检查怎么样?
如果我尝试用更具体的类型替换m a
,我会得到(如果我错了,请纠正我):
(((->) ??) a) -> (a -> (((->) ??) b)) -> (((->) ??) b)
相当于
(?? -> a) -> (a -> (?? -> b)) -> (?? -> b)
假设变量m
绑定到(?? -> a
),f
将绑定到a -> ?? -> b
,x
绑定到第二个??
。
我的推理是否正确?
答案 0 :(得分:6)
这是一个带三个参数的函数。那个类型检查怎么样?
据我所知,在当前上下文中这个函数签名:
bind m f x = f (m x) x
应该等于:
bind m f = \x -> f (m x) x
答案 1 :(得分:3)
要添加到swizard所说的内容(这是正确的),一种方法来检查类型类函数的类型签名,一旦它专门用于特定实例,就是将其写出来并查看psci是否同意:
> :type bind :: forall r a b. (r -> a) -> (a -> r -> b) -> (r -> b)
forall r a b. (r -> a) -> (a -> r -> b) -> r -> b
所以你的推理确实是正确的。如果我们写出了错误的类型,我们就会遇到类型错误:
> :type bind :: forall r. r -> r
Error found:
[...]
Could not match type [...] with [...]
[...]
另外,如果您还不知道,函数类型构造函数->
是右关联的,因此a -> (r -> b)
与a -> r -> b
相同。