我想实现一个递归安全max
函数,如果提供了一个空列表,则返回Nothing
;如果找到最大值,则返回Just a
。
一种幼稚的方法(如果提供了一个空列表,它只会返回零):
max' :: [Int] -> Int
max' [] = 0
max' (x:xs) | x < max' xs = max' xs
| otherwise = x
现在使用Prelude Maybe数据类型:
safeMax :: (Ord a) => [a] -> Maybe a
safeMax [] = Nothing
safeMax [x] = x
safeMax (x:y:xs) | x = safeMax (y:xs)
| otherwise = Just x
我收到一条消息,它无法构造无限数据类型a ~ Maybe a
。这是什么问题?
完整的错误消息是这样:
safemax.hs:33:15: error:
• Occurs check: cannot construct the infinite type: a ~ Maybe a
• In the expression: x
In an equation for ‘safeMax’: safeMax [x] = x
• Relevant bindings include
x :: a (bound at safemax.hs:33:10)
safeMax :: [a] -> Maybe a (bound at safemax.hs:32:1)
|
33 | safeMax [x] = x
解决方案:使用Just x
并使用x < y
:
safeMax :: (Ord a) => [a] -> Maybe a
safeMax [] = Nothing
safeMax [x] = Just x
safeMax (x:y:xs) | x < y = safeMax (y:xs)
| x > y = safeMax (x:xs)
| otherwise = Just x
我相信问题出在x < safeMax xs
。在这里,您尝试使用(<)
将a
与Maybe a
进行比较。在进行此比较之前,您需要从safeMax xs
解开返回值。