如何找到haskell定义的一般类型?

时间:2014-03-06 23:55:28

标签: haskell types

如何确定q2和q3的类型?当我输入时,模块给了我类型,但是手动执行此操作的可靠方法是什么?请帮忙。谢谢。

q2 x y z w = w (x y) (z y)

Type is: q2 :: (a -> b) -> a -> (a -> c) -> (b -> c -> d) -> d

q3 f g x y = (f.g) x == y

Type is: q3 :: Eq a => (b -> a) -> (c -> b) -> c -> a -> Bool

3 个答案:

答案 0 :(得分:11)

类型信息从现有结构流向新结构。让我们来看看你的例子:

q2 x y z w = w (x y) (z y)

这可能不是很明显,但是这个函数已经调用了一些类型化的Haskell原语。特别是,它使用具有类型

的函数应用程序
($) :: (a -> b) -> a -> b

实际上我们可以使用($)语法来使我们更加明确地使用函数应用程序。

q2 x y z w = (w $ x $ y) $ z $ y

或者,我们可以用Javascript-esque语法重新构造它,以便更清楚地看到应用程序

q2(x)(y)(z)(w) = w(x(y))(z(y))

无论如何,应该清楚有4个功能应用程序正在发生。从这些我们将产生的信息为我们提供q2的主要类型。


扩展类型推断的主要方法是“统一”,也就是说,如果我们知道单个事物具有类型AB,那么我们必须能够转换AB进入C,第三种类型同意AB。它可能只是AB偶数。

 | A      | B      | C      |
 |--------|--------|--------|
 | String | a      | String |
 | Int    | String | <fail> |
 | a      | b      | c      | (where we suppose a == b == c)
 | a -> b | c -> d | e -> f | (where we suppose a == c == e
 |        |        |        |               and b == d == f)

正如你所看到的,统一的另外两个特征:(1)它可能会失败,如果和(2)它有时会导致我们假设类型变量之间的平等。

一般来说,这就是推理的进展:我们为我们不知道的所有事物分配一个新的类型变量,然后尝试统一所有的部分。一路上我们可能会失败(因此我们说类型检查已经失败)或者我们将收集一大堆相等的信息,它们告诉我们我们已经引入了许多冗余类型变量。然后我们通过消除所有冗余变量来总结信息,直到我们不再需要陈述我们的等式。

 id     :: a -> a
    3   :: Num a => a
    3   :: Num b => b       -- make the variable fresh / not conflict with `a`
 id 3   :: Num c => c   (supposing a == b == c)
 id 3   :: Num a => a   (supposing nothing, we've forgotten about b and c)

因此,我们可以将此流程应用于q2。算术上做起来有点啰嗦,但很容易手工完成。我们正在寻找值q2的类型。我们知道q2需要4个参数并返回一些内容,因此我们可以立即构建该类型

q2 :: a -> b -> c -> d -> e

我们通过将xzw的类型与应用($)的类型统一为a和{{1必须与函数兼容

c

并且他们的输入参数必须具有与其参数值q2 :: (f -> g) -> b -> (h -> i) -> d -> e

兼容的类型
y :: b

最后,我们可以检查q2 :: (b -> g) -> b -> (b -> i) -> d -> e ,看看它是一个函数,它接受w类型的一个参数,并返回另一个函数,该函数接受x y类型的参数并返回东西

z y

q2 :: (b -> g) -> b -> (b -> i) -> (g -> (i -> j)) -> e 的右关联性我们通常写为

(->)

最后,我们知道q2 :: (b -> g) -> b -> (b -> i) -> (g -> i -> j) -> e 的返回类型是整个函数的返回类型

w

最重要的是,q2 :: (b -> g) -> b -> (b -> i) -> (g -> i -> j) -> j 是最终的,最常见的类型。


有关详情,请调查Hindley-Milner and Algorithm W。我已经松散地涵盖了大部分细节,但还有一些其他想法,所有这些都可以更仔细地检查。

答案 1 :(得分:5)

只是分析有意义的事情:

首先我们有

q2 x y z w = w (x y) (z y)

让我们分解一下,从仅仅看q2 x y z w我们得到它需要4个参数,以及返回类型:

q2 :: a -> b -> c -> d -> e

现在我们看一下这些,我们有w (x y) (z y),让我们把它分成小块:

  • (x y):我们使用x作为函数,y作为所述函数的参数,因此x的类型为x :: b -> f 。所以q2现在看起来像这样:

    q2 :: (b -> f) -> b -> c -> d -> e
    
  • (z y):具有相同的风格,所以我们可以说我们对x说的一样,但我们不知道x是否并且z返回相同的类型,因此z看起来像z :: b -> g。使q2看起来像这样:

    q2 :: (b -> f) -> b -> (b -> g) -> d -> e
    

    注意: (b -> f)(b -> g)会返回不同的类型,因为没有迹象(至少到现在为止)他们返回相同的类型。

  • w (x y) (z y):此处我们使用w作为函数,将(x y)(z y)作为参数,因此现在w的类型为w :: f -> g -> h {1}}。制作q2

    q2 :: (b -> f) -> b -> (b -> g) -> (f -> g -> h) -> e
    

    注意: w接受xz的返回类型的参数。

  • q2 x y z w = w (x y) (z y):我们可以看到此函数执行的最后一件事是使用w作为函数,因此w返回的是q2应返回的内容,所以最后q2看起来像这样:

    q2 :: (b -> f) -> b -> (b -> g) -> (f -> g -> h) -> h
    

希望它有所帮助,你应该自己q3来练习。如果您遇到困难,请告诉我。

答案 2 :(得分:1)

一篇了解Haskell类型系统的好文章也是“在Haskell中输入Haskell”,在那里你可以真正看到一个程序如何完成Hindley-Milner类型的推断。 http://web.cecs.pdx.edu/~mpj/thih/

由于Haskell是强类型的,因此您可以始终推断所有类型的所有函数,从假设一个不受限制的类型变量开始,该变量可能被上下文限制为更具体的类型或类型类(需要其他函数的其他函数)特定类型)。

学家亚伯拉罕森很好地解释了这一点。 :)