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.