我正在尝试使用折叠实现我自己的concat并在这里磕磕绊绊。为什么我会“无法创建无限类型”错误?
merge2 xs = foldl conc ([]) xs
where conc x y = (x : y)
答案 0 :(得分:1)
查看表达式x : y
中x和y的类型 - 由于{{1}的定义,y
的类型必须是x
类型的列表。 }}。如果您尝试遵循:
的类型,特别是其累加器函数的类型,您最终需要一个列表列表...
答案 1 :(得分:1)
在这里,您可以如何欺骗GHCi向您展示临时表达的类型。首先,你原来的定义,
f xs = foldl conc [] xs where conc x y = (x : y)
给出了关于"无限类型"的错误" a = [a]" 。现在,将conc
中的foldl
替换为其他内容:
f xs = foldl g [] xs where conc x y = (x : y) ; g = g
那里没有类型错误!如果仍有错误,请将某个表达式中使用的每个标识符替换为g2 = g2
,g3 = g3
等。此类定义等同于定义g = undefined
,其使用会导致错误,但更重要的是对我们而言根据需要,它的类型可以随意变成任何东西。
现在的诀窍是将它定义为一个简单的值,例如布尔值:
f xs = foldl g [] xs where conc x y = (x : y) ; g = True
这给我们一个关于" a - >之间类型不匹配的错误b - > a" 和" Bool" 。我们知道True
的类型为Bool
,因此我们得出结论:g
必须是a -> b -> a
类型。我们也可以使用:t
命令直接找到它:
Prelude> :t foldl
foldl :: (a -> b -> a) -> a -> [b] -> a
-------------
接下来,我们现在可以将conc
与一些简单的值进行比较:
f xs = foldl g [] xs where conc x y = (x : y) ; g = g ; h = conc == True
我们再次在" a - >之间出现类型不匹配错误。 [a] - > [a]" 和" Bool" 。 True :: Bool
(类型为Bool
),conc :: a -> [a] -> [a]
。最初我们在g
现在使用它,因此它们的类型必须匹配:
g :: a -> b -> a
conc :: a -> [a] -> [a]
------
a ~ [a]
这是不可能的。