Vincent Zhou
Vincent Zhou

Reputation: 141

custom type define in haskell

Im new to haskell, I defined a custom list type.But when I try to define this function mymaximum. I notice that it only works if a is of type Num. what should I change if I want it to work with all types, for example 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

Upvotes: 1

Views: 458

Answers (1)

Will Ness
Will Ness

Reputation: 71119

First of all, if you try to load the definition as given you get an error message,

....
 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
....

So this suggests you need to change the type signature to

mymaximum :: (Num a) => List a -> a

Now the error message is

....
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
....

and just the same, we change the type signature to

mymaximum :: (Num a, Ord a) => List a -> a

and now GHCi responds:

mymaximum :: (Num a, Ord a) => List a -> a

Meaning, it accepted the definition with its type signature.

Now this fucntion will work with all types that implement both Num and Ord typeclasses.

Int is one, Float is another. Char is not. But if you import Data.Char, you can use the functions

chr :: Int -> Char

ord :: Char -> Int

to get around this, by mapping ord over your List Char value (you'll have to also define your own map function for that ... perhaps), finding your maximum, then working backwards with chr to recover the character.

update: as you've noticed, special casing 0 as the maximum value of an empty list is not The Right Thing to do. Making a one-element list to be your base case is a good solution for that. Now the Num a constraint can be removed and the function will work as is for List Char arguments as well, or any Ord a => List a type of value, producing an Ord a => a type of value as a result.

One caveat though: you still need to handle the empty list case, perhaps by calling error with a specific error message, like

mymaximum ListEnd = error " mymaximum: empty list is not allowed! "

Upvotes: 4

Related Questions