Haskell - 无法将预期类型 ‘b’ 与实际类型 ‘a’ 匹配

标签 haskell recursion

刚刚开始学习Haskell并且 我试图实现一个 max 函数来递归地查找列表的最大值

max' :: (Num b) => [a] -> b
max' [] = 0
max' (x:xs)
    | x > max' xs = x
    | otherwise = max' xs

但是在尝试编译时出现错误

Couldn't match expected type ‘b’ with actual type ‘a’ ‘a’ is a rigid type variable bound by the type signature for: max' :: forall b a. (Num b, Num a) => [a] -> b at implementingFunctions.hs:5:1-34 ‘b’ is a rigid type variable bound by the type signature for: max' :: forall b a. (Num b, Num a) => [a] -> b at implementingFunctions.hs:5:1-34

任何人都可以帮助我理解出了什么问题吗 ?

最佳答案

max'[a] 作为输入(基于签名) : a 的列表s。但你返回一个b 。这意味着您已经编写了 - 无论列表中元素的类型如何 - 我们都可以选择任何类型 b作为我们想要的输出,只要是 Num b 。但这没有意义。如果我们输入一个字符串列表,我们当然可以计算“最大字符串”(按字典顺序),但我们不能将其返回为 Num .

另一个问题是您使用 (>) :: Ord a => a -> a -> Bool功能(作为 guard )。但您没有在函数签名中指定输入元素的类型必须是 Ord 的实例。类型类。所以你不能比较元素。

最小的修复是将输入类型限制为 b还有:

max' :: <b>(Ord b, </b>Num b<b>)</b> => [<b>b</b>] -> b
max' [] = 0
max' (x:xs)
    | x > max' xs = x
    | otherwise = max' xs

话虽如此,返回 0 并没有多大意义。如果我们提供一个空列表。这会导致一个奇怪的事实:max []实际上大于max [-1] :通常我们期望超集的最大值大于或等于集合的最大值。

所以max'函数可能最好被视为非全函数:并非每个输入都会产生输出的函数。在这种情况下,空列表不会。

我们可以将其重写为错误:

max' :: Ord b => [b] -> b
max' [] = <b>error "Empty list"</b>
<b>max' [x] = x</b>
max' (x:xs@(_:_))
    | x > max' xs = x
    | otherwise = max' xs

现在有三种模式:(1) 空列表,(2) 单例列表,(3) 至少有两个元素的列表。

然而,编写错误并不总是处理非完整函数的好方法,因为人们无法在类型签名中看到函数是非完整的。另一种方法是使用 Maybe b 作为返回类型。这将是 Nothing如果没有最大值,或者 Just x如果有的话:

max' :: Ord b => [b] -> <b>Maybe </b>b
max' [] = <b>Nothing</b>
max' [x] = <b>Just x</b>
max' (x:xs@(_:_))
    | <b>y <- max' xs = max x y</b>
    | otherwise = Nothing

或更短:

max' :: Ord b => [b] -> Maybe b
max' [] = <b>Nothing</b>
max' [x] = <b>Just x</b>
max' (x:xs@(_:_)) = <b>fmap (max x) (max' xs)</b>

例如:

Prelude> max' []
Nothing
Prelude> max' [1,4,2,5]
Just 5
Prelude> max' [-3]
Just (-3)

关于Haskell - 无法将预期类型 ‘b’ 与实际类型 ‘a’ 匹配,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47210822/

相关文章:

python - 在递归函数中添加括号

Javascript递归循环项目到数组

c++ - (C++) 在没有递归的情况下实现指数函数求值器?

list - Erlang:递归与列表

haskell - Haskell 中的模糊实例解析

haskell - 理解 Data.Functor.Constant 构造函数和应用规律

haskell - 类型构造函数和类型常量(和类型变量): What's the difference?

haskell - 为什么所有递归模式同义词都被拒绝?

haskell - 约束类型类或实例的派生变量

haskell - 实现 Haskell 对数函数