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

标签 haskell

这个问题在这里已经有了答案:





Defining a function by equations with different number of arguments

(3 个回答)


5年前关闭。




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

我有一个函数,叫做 dealWithIt。它看起来像这样:

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

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

据我所知,只要它可以传递给底层函数链,我是否明确指定接收到的参数并不重要。这意味着以下两个定义应该是等效的:
dealWithIt xs = foldl f "" xs
dealWithIt = foldl f ""

到现在为止还挺好。假设我现在想通过模式匹配添加一个特殊情况:
dealWithIt [] = "Empty list :("

这就是事情变得奇怪的地方。如果我没有明确指定 xs 参数,我会收到以下错误:
Equations for ‘dealWithIt’ have different numbers of arguments

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

最佳答案

这只是一个规则。按情况定义函数:

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 的第一个参数必须具有无限类型。无限类型错误通常不利于调试。)

关于haskell - 为什么 Haskell 无法自动解析参数数量?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33764456/

相关文章:

list - 过滤我自己类型的列表 - 元组?

haskell - 模式匹配后多态性丢失

haskell - "applicative"是什么意思?

haskell - Haskell 中 Cofree CoMonad 的一些激励示例是什么?

haskell - 什么是异态?

haskell - 如何在 Haskell 中进行控制流

python - 从 Haskell 到 Python : how to do currying?

haskell - 笛卡尔类的这些类扩展是做什么用的?

haskell - 当我添加不相关的定义时,为什么会在此程序中出现类型错误?

haskell - 如何即时使用 IO monad 输出