为什么为这个Haskell函数提供一个空列表会给予编译器错误?

svgewumm  于 2022-11-14  发布在  其他
关注(0)|答案(1)|浏览(137)

下面的代码来自于《学一个好的 haskell 》一书:

maximum' :: (Ord a) => [a] -> a
maximum' [] = error "maximum of empty list"  
maximum' [x] = x  
maximum' (x:xs)   
    | x > maxTail = x  
    | otherwise = maxTail  
    where maxTail = maximum' xs

它在非空列表上运行良好,但提供了一个空列表:

main = print $ maximum' []

会产生下列编译器错误:
由于使用“maximum”而产生的二义性类型变量“a0”阻止了约束“(Ord a0)”的求解。
为什么?当提供一个空列表时,代码不应该捕获它吗?我不明白错误信息。

czq61nw1

czq61nw11#

由于使用“maximum”而产生的二义性类型变量“a0”阻止了约束“(Ord a0)”的求解。
这意味着当您调用maximum' []时,[]的类型是不清楚的:它可以是[Int][()]或其它。
在这个特殊的例子中,不同类型的列表的结果恰好是相同的。编译器在这里无法证明这一点,通常情况下也不是这样。考虑下面这个函数:

readAndPrepend :: (Read a, Show a) => String -> [a] -> String
readAndPrepend s xs = show (read s : xs)

如果调用readAndPrepend "42" [],结果应该是什么是不明确的:

ghci> readAndPrepend "42" ([] :: [Int])
"[42]"
ghci> readAndPrepend "42" ([] :: [Double])
"[42.0]"
ghci> readAndPrepend "42" ([] :: [()])
"[*** Exception: Prelude.read: no parse
ghci>

换句话说,a类型变量是“未解”的,就像数学方程中的自由x一样。
您需要做的是选择一个您希望列表成为的类型并显式指定它:

main = print $ maximum' ([] :: [()])

相关问题