部分应用程序的说明 - 加入

时间:2012-08-13 16:24:19

标签: haskell types partial-application

为什么部分应用具有不同签名的功能有效?

Control.Monad.join为例:

GHCi> :t (=<<)
(=<<) :: Monad m => (a -> m b) -> m a -> m b
GHCi> :t id
id :: a -> a
GHCi> :t (=<<) id
(=<<) id :: Monad m => m (m b) -> m b

为什么它接受id :: a -> a代替(a -> m b)参数,因为它们明显不同?

3 个答案:

答案 0 :(得分:10)

=<<的类型签名表示第一个参数是从a(任何)到b的monad的函数。

嗯,m b算什么了,对吗?因此,我们可以在m b中替换a

(=<<) :: Monad m => (m b -> m b) -> m (m b) -> m b

id类型表示它是从任何东西到同一个东西的函数。因此,如果我们在m b(不忘记monad约束),我们得到:

id :: Monad m => m b -> m b

然后你可以看到类型匹配。

答案 1 :(得分:3)

这里使用的一些有用的概念:

  1. 通过将a的每个实例替换为任何其他类型a,可以将具有变量t的任何类型转换为其他类型。因此,如果您的类型为a -> b -> c,则可以将a -> d -> c替换为a -> b -> Intb来获取类型d或类型c分别为Int
  2. 任何两种可以通过替换相互转换的类型都是等效的。例如,a -> bc -> d是等效的(acbd)。
  3. 如果类型t可以转换为t'类型,但t'无法转换回t,那么我们会说t' 1}}是t特化。例如,a -> aa -> b
  4. 的特化

    现在,通过这些非常有用的概念,您的问题的答案非常简单:即使函数&#34;原生&#34;类型不完全匹配,它们是兼容的,因为它们可以被重写或专门用于获得完全匹配。 Matt Fenwick的回答显示了针对这种情况的专业化。

答案 2 :(得分:2)

它尝试将am b统一起来,并简单地决定a必须是m b,因此(=<<)的类型(假设{ {1}})为a ~ m b,一旦您将其应用于Monad m => (mb -> m b) -> m (m b) -> m b,您就会被id留下。