
Oleg has just pointed out that the 'Show' constraint bellow does not work if you try and use a function from the show class (say 'show'), as the function: test2 l = show l has the type: test2 :: forall a. (Show a) => a -> String The technique below works to constrain for membership of a class, So we know all elements in the list are instances of show, but we cannot call functions. The best thing here is to let the compiler infer any remaining constraints using: showList :: ConstrainedList SHOW l => l -> String showList = undefined test l | False = showList l | otherwise = show (hHead l) Here the 'False' guard is never executed, but its type is unified with the inferred type for 'show l'... ghci shows us: *Main> :type test test :: forall b a. (Show a, ConstrainedList SHOW (HCons a b)) => HCons a b -> String In other words use constraints only to enforce explicit requirements, the compiler can safely infer all required constraints from the code (IE just don't give signatures for the functions). Keean. Keean Schupke wrote:
You can avoid the need to declare a new class for each constrained list by using the following:
class Constraint c a
data SHOW instance Show a => Constraint SHOW a
class HListConstraint c l instance HListConstraint c HNil instance (Constraint c a,HListConstraint c l) => HListConstraint c (HCons a l)
You can now constrain a list as follows:
assertShow :: HListConstraint SHOW l => l -> l assertShow = id
The type parameter can be made first class using:
showConstraint :: SHOW showConstraint = undefined
So we can now pass this as a parameter:
assertConstraintOnHList :: HListConstraint c l => c -> l -> l assertConstraintOnHList _ = id