为什么Haskell无法自动解析参数的数量?

时间:2015-11-17 18:33:07

标签: haskell

我是Haskell的新手,我对以下行为感到困惑:

我有一个名为dealWithIt的函数。它看起来像这样:

dealWithIt :: (Show a) => [a] -> String
dealWithIt = foldl f ""
  where f memo x = memo ++ (show x)

一切都很好,它按预期工作,它获得一个showables列表并将它们连接成一个字符串。

据我所知,只要可以将其传递给基础函数链,我是否明确指定了收到的参数并不重要。这意味着以下两个定义应该是等价的:

dealWithIt xs = foldl f "" xs
dealWithIt = foldl f ""

到目前为止一切顺利。假设我想通过模式匹配现在添加一个特殊情况:

dealWithIt [] = "Empty list :("

这就是事情变得奇怪的地方。如果我没有明确指定xs参数,我会收到以下错误:

Equations for ‘dealWithIt’ have different numbers of arguments

我可以忍受它,但对我来说真的很有趣的是,为什么Haskell无法检测到正在发生的事情并报告错误,即使这两个变体只有一个参数?

1 个答案:

答案 0 :(得分:4)

这只是一个规则。按案例定义函数:

f p0 p1 = e0
f p2 p3 = e1
对于所有方程,

必须在左侧的函数参数中具有相同数量的模式。

部分原因是为了简化语言的定义; Haskell标准根据 case表达式定义该函数定义:

f x0 x1 = case (x0, x1) of
    (p0, p1) -> e0
    (p2, p3) -> e1

现在考虑如果你能说

会发生什么
f p0 p1 = e0
f p2 = e1 -- `e1` is a function

语言标准必须专门处理该案例,并将其定义为

f x0 x1 = case (x0, x1) of
    (p0, p1) -> e0
    (p2, _) -> e1 x1 -- Note that the argument to `e1` has to be supplied explicitly

这对于通常不明智的事情来说是一种不必要的并发症。

此外,请考虑foldr

的定义
foldr f z [] = z
foldr f z (x:xn) = f x (foldr f z xn)

假设您正在键入它而忘记了第一个等式的f

foldr z [] = z
foldr f z (x:xn) = f x (foldr f z xn)

当前规则允许捕获这样的拼写错误:编译器可以抱怨在不同的等式中有不同数量的参数。否则你会得到一些令人困惑的类型错误,这可能很难调试。 (可能您会收到错误,因为第一个等式中的z必须与第二个等式中的f具有相同的类型,并且第一个等式中的z必须具有相同的类型在第二个等式中为f x (foldr f z xn),因此foldr的第一个参数必须具有无限类型。无限类型错误通常无法调试。)