I've been reading about making our own types and type classes from Learn You a Haskell for Great Good. I don't quite understand the behaviour of the Haskell compiler when I add a type constraint to my data declarations.
For example, I have
{-# LANGUAGE DatatypeContexts #-}
data (Ord a) => OrderedValue a = OrderedValue a
getOrderedValue :: OrderedValue a -> a
getOrderedValue (OrderedValue a) = a
As can be seen above, I have a type constraint on my data declaration, stating that any value that is contained inside an OrderedValue must have an Ord instance.
I tried compiling this code and the compiler spit out
• No instance for (Ord a) arising from a use of ‘OrderedValue’
Possible fix:
add (Ord a) to the context of
the type signature for:
getOrderedValue :: forall a. OrderedValue a -> a
• In the pattern: OrderedValue a
In an equation for ‘getOrderedValue’:
getOrderedValue (OrderedValue a) = a
Changing the definition of getOrderedValue to
getOrderedValue :: (Ord a) => OrderedValue a -> a
getOrderedValue (OrderedValue a) = a
expectedly fixed the problem.
My question is - why is the compiler complaining here? I assumed the compiler should be able to infer that the a being pattern matched in
getOrderedValue (OrderedValue a) = a
has an Ord instance, because the OrderedValue value constructor is for constructing instances of type OrderedValue that has a type parameter a that has an Ord instance.
Phew, that was a mouthful.
Thanks.
EDIT - I had a look at the alternate answers that @melpomene suggested, thanks for that. However, I'm looking for an answer that describes why the Haskell language designers chose to implement it this way.
sort :: IO Double -> Char, then this surely must cause a compile-time error. The point is that you can ask the compiler what the (most general) correct signature is, rather than writing it yourself – though more often it actually works better to start with the signature and let the compiler help you with the implementation instead. And, sometimes signatures are actually needed, in particular when Rank-2 types are involved. - leftaroundaboutdatadeclaration. They really add nothing to your type and only cause headaches. There are better alternatives. - Bakuriu