我在尝试理解Haskell如何确定函数类型时感到有些困惑。这是一个例子:
boolFcn x y = x/=3 && y/=4
当我检查上述功能的类型时,它给出了结果:
(Num a1, Num a, Eq a1, Eq a) => a -> a1 -> Bool
这是另一个例子:
triangles = [ (a,b,c) | c <- [1..10], b <- [1..10], a <- [1..10] ]
:t
triangles
上的(Num t2, Num t1, Num t, Enum t2, Enum t1, Enum t) => [(t, t1, t2)]
结果为:
a, a1
我脑子里出现了一些问题,我自己也很难解决问题:
t,t1
文字组成,而三角形的类型由a
文字组成? t
和(Num a, Eq a) => a -> a -> Bool
之间有什么区别吗?为什么boolFcn的类型不能简化为:
a
a1
和a
具有相同的类型类别,那么为什么我只能使用一个let sumthis x y = if x > y then x+y else x-y
来编写它们?当我检查功能的类型时:
(Ord a, Num a) => a -> a -> a
我得到了一个结果:
(Ord a, Num a, Ord a1, Num a1) => a -> a1 -> a
为什么不导致:
{{1}}
对不起,如果这个问题很简单,不过我很乐意听到这个问题的任何解释/提示。
答案 0 :(得分:6)
是的,a
和t
在这些示例中基本相同。差异只是类型推断算法的副作用。
嗯,在boolFcn
中,(Num a, Eq a) => a -> a -> Bool
不够通用,因为前两个参数不一定是同一类型。请考虑以下呼叫:
boolFcn (4::Int) (4::Double)
这是有效的,因为Int
和Double
都是Num
和Eq
类型类的成员,但它们显然不是同一类型。在sumthis
示例中,x
和y
必须是同一类型,因为它们用作需要相同类型参数的函数的输入。
我们可以通过选中返回:t (+)
的{{1}}来查看。由于(+) :: Num a => a -> a -> a
的参数必须是同一类型,+
和x
必须是同一类型,因此y
必须要求相同类型的参数。因此
sumthis
无效。
答案 1 :(得分:4)
首先,类型中的变量名称无关紧要。它们是任意命名的,但给定类型的内容将是相同的。例如,a -> b -> b =/= a -> b -> a
,但是a -> b == c -> d
(只要它们不会出现在相同类型的签名中!)。类型检查器为变量类型变量提供了多态值,因此不必担心命名方案的细微差别:它们无关紧要。它们只是变量。
关于类型检查器如何实际确定表达式的类型,让我们看看你的第一个例子:
(Num a1, Num a, Eq a1, Eq a) => a -> a1 -> Bool
boolFcn x y = x/=3 && y/=4
首先,类型检查员看到x /= 3
。这意味着x
必须是Eq
,因为(/=)
是Eq
类型类的一部分,而且,它必须是Num
,因为3
在编译期间被解释为多态Num
类型。 y /= 4
也会发生同样的情况,但y
和x
与(&&)
的使用不相互影响。这说明x
和y
不需要是同一类型,因此标题中的类型变量不同。最后,(&&)
返回Bool
,这就是函数返回的内容。
你的第二个例子因为一些语法糖而有点棘手。
(Num t2, Num t1, Num t, Enum t2, Enum t1, Enum t) => [(t, t1, t2)]
triangles = [ (a,b,c) | c <- [1..10], b <- [1..10], a <- [1..10] ]
基本上,当您执行xs = [a..b]
之类的操作时,xs
的类型必须为Enum a => [a]
。直观地说,不可能有一系列无法按顺序列举的东西。接下来,这些数字再次被解释为多态Num
类型。但为什么我们在签名中有三个不同的类型变量,每个变量都必须是Num
和Enum
? Num
类型实际上不必相同,因为允许元组(a, b, c)
在其第一,第二和第三点中具有不同类型的数据。因此,每个[1..10]
可以被解释为不同可枚举数字的列表(即(Int, Integer, Int)
或(Integer, Integer, Int)
,并且一切正常。如果你是收集列表而不是元组,如下所示:
triangles = [ [a,b,c] | c <- [1..10], b <- [1..10], a <- [1..10] ]
a
,b
和c
现在需要具有相同的类型,因此签名更改为triangles :: (Num t, Enum t) => [[t]]
。