Constraints with Type Variables Applied to Multiple Types Cause Illegal Class Constraint Errors
The function
f :: Eq (a Bool Bool) => a Bool Bool -> a Bool Bool -> Bool
f = (==)
should be accepted by PAKCS, but the following error message is reported:
Illegal class constraint Eq (a Bool Bool)
Constraints must be of the form C u or C (u t1 ... tn),
where C is a type class, u is a type variable and t1, ..., tn are types.
|
1 | f :: Eq (a Bool Bool) => a Bool Bool -> a Bool Bool -> Bool
| ^^
This error is caused by the function rootType
, which is a subfunction of checkConstraint
:
checkConstraint :: Constraint -> TSCM Constraint
checkConstraint c@(Constraint spi qcls ty) = do
checkClass False qcls
ty' <- checkType ty
unless (isVariableType $ rootType ty') $ report $ errIllegalConstraint c
return $ Constraint spi qcls ty'
where
rootType (ApplyType _ ty' _) = ty'
rootType ty' = ty'
rootType
is not defined recursively and only removes a single ApplyType
, which means that type variables that are applied to multiple types are not identified as type variables. For example, a Bool Bool
is represented in the AST by ApplyType (ApplyType (VariableType "a") (ConstructorType "Bool")) (ConstructorType "Bool")
(simplified), so rootType
returns ApplyType (VariableType "a") (ConstructorType "Bool")
, which is not identified as a type variable by isVariableType
.