我对haskell不熟悉,我定义了一个自定义列表类型,但是当我尝试定义此函数mymaximum时。我注意到,仅当a为Num类型时才有效。如果我希望它可以与所有类型(例如Char)一起使用,应该怎么更改?
data List a = ListNode a (List a) | ListEnd
mymaximum::List a -> a
mymaximum ListEnd = 0
mymaximum (ListNode x xs)
| x > maxxs = x
| otherwise = maxxs
where maxxs = mymaximum xs
答案 0 :(得分:4)
首先,如果您尝试按照给定的方式加载定义,则会收到错误消息,
....
No instance for (Num a) arising from the literal `0'
Possible fix:
add (Num a) to the context of
the type signature for mymaximum :: List a -> a
....
因此,这表明您需要将类型签名更改为
mymaximum :: (Num a) => List a -> a
现在错误消息是
....
Could not deduce (Ord a) arising from a use of `>'
from the context (Num a)
bound by the type signature for mymaximum :: Num a => List a -> a
at <interactive>:59:14-35
Possible fix:
add (Ord a) to the context of
the type signature for mymaximum :: Num a => List a -> a
....
同样,我们将类型签名更改为
mymaximum :: (Num a, Ord a) => List a -> a
现在GHCi做出响应:
mymaximum :: (Num a, Ord a) => List a -> a
意思是,它接受带有类型签名的定义。
现在,此功能将与实现Num
和Ord
类型类的所有类型一起使用。
Int
是一个,Float
是另一个。 Char
不是。但是如果您import Data.Char
,则可以使用功能
chr :: Int -> Char
ord :: Char -> Int
要解决此问题,请在您的ord
值上映射List Char
(也许您还必须为此定义自己的map
函数……),找到最大值,然后向后与chr
一起恢复字符。
更新:正如您所注意到的,作为空列表的最大值的特殊大写字母0
是 not 正确的事情。将单元素列表作为您的基本案例是一个很好的解决方案。现在可以删除Num a
约束,并且该函数也将按List Char
参数或任何Ord a => List a
类型的值的方式工作,并产生Ord a => a
类型的值,如下所示:结果。
请注意:您仍然需要处理空列表情况,可能是通过调用error
并显示特定错误消息,例如
mymaximum ListEnd = error " mymaximum: empty list is not allowed! "