在haskell中定义自定义类型

时间:2018-08-18 08:06:38

标签: haskell types max typeclass

我对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

1 个答案:

答案 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

意思是,它接受带有类型签名的定义。

现在,此功能将与实现NumOrd类型类的所有类型一起使用。

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! "