我刚开始学习哈斯克尔。我在函数定义中有一些declare函数类型的混淆。例如,如果我们想要定义一个foldr函数:
foldr :: (a->b->b)->b->[a]->b
foldr f v [] = v
foldr f v (x:xs) = f x (foldr f v xs)
因此,foldr(+)0 [1,2,3,4] = sum [1,2,3,4] = 10.
我的问题是:我可以将其更改为:
foldr :: (a->a->a)->a->[a]->a
OR:
foldr :: (a->b->c)->x->[y]->z
我没有找到解释定义中字母选择/要求的地方。谢谢!
更新: 我测试了它:
foldr :: (a->b->c)->x->[y]->z
得到以下错误:
Couldn't match type `y' with `a'
`y' is a rigid type variable bound by
the type signature for folderr :: (a -> b -> c) -> x -> [y] -> z
at test.hs:3:1
`a' is a rigid type variable bound by
the type signature for folderr :: (a -> b -> c) -> x -> [y] -> z
at test.hs:3:1
如果将所有内容更改为a,则有效。我一定在这里错过了一些观点。
正如@ sepp2k的评论中所述。我使用以下简单示例进行了测试:
folderr :: (a->b->b)->b->[a]->b
folderr f v [] = v
folderr f v (x:xs) = f x (folderr f v xs)
myop :: Int -> Bool -> Bool
myop x y | x > 0 = True && y
| otherwise = False && y
folderr(myop)True [3,3,222] - >真正 folderr(myop)True [3,2,-1] - >假
所以a,b只意味着类型不同或不同。
答案 0 :(得分:3)
类型变量的具体名称无关紧要,即类型a -> b -> c
,x -> y -> z
和foo -> bar -> baz
都完全等效。
重要的是您是多次使用相同的类型变量还是使用不同的变量。这是a -> b
与a -> a
不同的类型。具体而言,a -> b
更为通用,因为在具体类型Int -> Int
,String -> String
,Int -> String
和String -> Int
中,a -> a
仅匹配前两个(分别为a = Int
和a = String
),而a -> b
将匹配所有四个。