无法与实际类型'a'匹配预期类型'b'

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

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

但在编译时遇到错误

无法与实际类型'a'匹配预期类型'b''a'是由类型签名绑定的刚性类型变量:max':: forall b a。 (数字b,数字a)=> [a] - > b在实现函数.hs:5:1-34'b'是一个刚性类型变量,其类型签名为:max':: forall b a。 (数字b,数字a)=> [a] - > b在实现函数.hs:5:1-34

任何人都可以帮助我了解最新的错误?


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

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

最小的修正是将输入类型限制为b

max' :: (Ord b, Num 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' [] = error "Empty list"
max' [x] = x
max' (x:xs@(_:_))
    | x > max' xs = x
    | otherwise = max' xs

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

然而,编写错误并不总是处理非全部函数的好方法,因为在类型签名中看不到函数是非全部的。 另一个要做的是使用Maybe b作为返回类型。 如果没有最大值,那么这将是一个Nothing ,如果有一个,则为Just x

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

或更短:

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

例如:

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

你的函数需要一个东西的列表并返回这些东西之一。 但函数的类型签名表示它需要一个[a]的列表并返回一个完全不同的东西b 。 这阻碍了编译器。 它不能使声明的类型签名与实际实现(又名“类型检查”)相一致。

要解决此问题,请使类型签名与实现匹配:

max' :: (Num a) => [a] -> a 
链接地址: http://www.djcxy.com/p/43437.html

上一篇: Couldn't match expected type ‘b’ with actual type ‘a’

下一篇: Method signature Haskell user defined type