2010-07-24 43 views
3

同时通过真实世界哈斯克尔工作,我尝试使用下面的代码的解决方案来完成回文锻炼:为什么这种形式可以接受,但另一种形式会引发类型错误?

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]“错误我答。有人能解释这一点吗?

+0

表达式'(something)** ** never **与形式'[something]'的相应表达式具有相同的类型,您只需用方括号替换括号即可。那*总是很重要! – Ben 2013-12-17 00:29:02

回答

10

在最后一行中,您尝试将非列表追加到列表。 head list给出列表中的第一项,即a。当您尝试使用++进行追加时,不能将不是列表的东西追加到列表中。通过附加[head list],您将一个项目的列表附加到另一个列表。在这种情况下,[]构造单个项目列表。

7

++运算符的类型为[a] -> [a] -> [a],即它需要两个某种类型的列表并生成另一个相同类型的列表。 OTOH head函数具有类型[a] -> a,即它接受某种类型的列表并返回该类型的值。在你的第一个例子++得到[a]在左边和a在右边。试图统一这些类型检查器会产生该错误。在第二个示例中,您从head的结果构建了单元素列表,并且它的类型为[a],因此类型检查器很高兴。

10

假设你是类型检查,您会看到这一点:

(tail list) ++ (head list) 

你已经知道,'名单的事情的清单。所以,你开始:

list::[a] 

那么这一定是真实的:

(tail list)::[a] 

这:

(head list)::a 

但随后有`++其希望它的两个参数有相同的类型。但是,这意味着,

a == [a] 

或通过取代:

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

这确实是一个无限型。