Let\'s say I want to define a tree like this:
{-# LANGUAGE DatatypeContexts #-}
class Node a where
getContent :: (Num a) => a
data (Node a) => Tree
Are you sure datatype contexts actually did what you think it did? It was deprecated because it was basically useless and widely considered a misfeature, since all it did was force you to add extra constraints without providing any guarantees about types beyond what you'd have had without it.
The replacement, such as it is, that actually does something useful, is GADT syntax. The equivalent of your type would look like this:
data Tree a where
Leaf :: (Node a) => a -> Tree a
Branch :: (Node a) => a -> Tree a -> Tree a -> Tree a
In this case, you need the Node
constraint when creating a Tree
value, but when pattern matching on a Tree
value you also get an automatic guarantee that a Node
instance exists, making the instance available without even needing it in the type of the function receiving Tree a
as an argument.