Reputation: 141
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
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