Haskell 为什么这个表单可以接受,而另一个表单会引发类型错误?

Haskell 为什么这个表单可以接受,而另一个表单会引发类型错误?,haskell,Haskell,在处理真实世界的Haskell时,我尝试使用以下代码解决方案完成回文练习: palin :: [a] -> [a] palin list = list ++ rev list where rev list | null list = [] | otherwise = rev (tail list) ++ (head list) 它引发了一个“无法构造无限类型错误。但是,只需将标题列表周围的括号替换为方括号,它就能正常工作,如以下示例所示

在处理真实世界的Haskell时,我尝试使用以下代码解决方案完成回文练习:

palin :: [a] -> [a]
palin list = list ++ rev list
    where rev list
           | null list = []
           | otherwise = rev (tail list) ++ (head list)
它引发了一个“无法构造无限类型错误。但是,只需将标题列表周围的括号替换为方括号,它就能正常工作,如以下示例所示:

palin :: [a] -> [a]
palin list = list ++ rev list
    where rev list
           | null list = []
           | otherwise = rev (tail list) ++ [head list]

我真的不明白它为什么重要,也不明白“不能构造无限类型a=[a]“错误意味着。有人能解释一下吗?

在最后一行中,您试图将非列表附加到列表中<代码>标题列表给出列表的第一项,类型为
a
。当您尝试使用
++
进行追加时,不能将非列表的内容追加到列表中。通过添加
[标题列表]
,您将在另一个列表中添加一个包含1项的列表。在这种情况下,
[]
构造单个项目列表。

++
运算符具有类型
[a]->[a]->[a]
,即它接受某一类型的两个列表,并生成另一个相同类型的列表。OTOH
head
函数具有类型
[a]->a
,即它获取某个类型的列表并返回该类型的值。在第一个示例中,
++
[a]
放在左手,将
a
放在右手。尝试统一这些类型类型检查器会产生该错误。在第二个示例中,您根据
head
的结果构建了一个单元素列表,它的类型为
[a]
,因此类型检查器很高兴。

假设您是类型检查器,您会看到这样的结果:

(tail list) ++ (head list)
你已经知道,“列表”是一个列表。因此,你从以下几点开始:

list::[a]
那么这一定是真的:

(tail list)::[a]
这是:

(head list)::a
但是还有一个“++”,它希望它的两个参数具有相同的类型。但这意味着

a == [a] 
或通过替换:

a == [a] == [[a]] == [[[a]]] ...etc.

这确实是一个无限类型。

形式为
(某物)
的表达式从来没有与形式为
[某物]
的相应表达式具有相同的类型,其中您只需将括号替换为方括号。这总是很重要的!