为部分应用的函数绑定 class 个实例

Bind class instance for partially applied functions

Prelude中Bindclass的定义是:

class Apply m <= Bind m where
  bind :: forall a b. m a -> (a -> m b) -> m b

它可以被理解为一个函数,它接受两个个输入参数,一个单子上下文中的值(m a)和一个函数(a -> m b)并在 monadic 上下文中返回一个值 (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 将绑定到第二个 [=26] =].

我的推理是否正确?

Which is a function taking three parameters. How does that typecheck?

据我所知,在当前上下文中这个函数签名:

bind m f x = f (m x) x

应该等于:

bind m f = \x -> f (m x) x

为了补充 swizard 所说的(这是正确的),一种检查类型 class 函数的类型签名的方法是,一旦它被专门用于特定实例,就是将其写出来并查看如果 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 [...]
[...]

此外,以防万一您还不知道,函数类型构造函数 -> 是 right-associative,因此 a -> (r -> b)a -> r -> b 相同。