Haskell prime has decided to depricate DatatypeContexts.
data (Eq e) => HasEq e = HasEq e
In haskell98, 2010 these are not typically usable as you might expect
eq :: HasEq e -> HasEq e -> Bool eq (HasEq e) (HasEq e') = e == e'
Would give a missing context error, so contexts always had to be specified.
eq :: (Eq e) => HasEq e -> HasEq e -> Bool eq (HasEq e) (HasEq e') = e == e'
An alternative in terms of GADTs that works as expected has been suggested.
data HasEq e where HasEq :: (Eq e) => e -> HasEq e eq :: HasEq e -> HasEq e -> Bool eq (HasEq e) (HasEq e') = e == e'
Problems with GADT alternative
For performance sensitive types this might be problematic since they are always stored in a box that could be bottom and that needs to be checked at runtime.
If you have a num container,
data IsNum n where IsNum :: (Num n) => n -> IsNum n
you can not write the type of the following expression without stating the type class
IsNum $ fromInteger 1 :: (Num n) => IsNum n
Syntactic sugar for explicit type annotations + Constructor type change
How can you get a value of type
- Using a Constructor (also in a pattern):
Use the same trick as with GADTs?
Just make the type signature of the constructor
(Eq a) => a -> HasEq a
- Explicit type signature
(undefined :: HasEq a): For all free variables in
Eq (...)to the context where the variable is bound.
Listing of all places where explicit types appear.
type simpletype = typejust a simple type synonym no need to do anything
data [context =>] simpletype = constrs [deriving]check the constructors for types with DatatypeContexts. Place all found contexts in
context. If the context is not empty? Change the constructor types to:
Constr :: context => ...
- same for newtype
class [scontext =>] tycls tyvar [where cdecls]Nothing to do really.
- instance [scontext =>] qtycls inst [where idecls] Make InferDatatypeContext imply FlexibleContexts. Check inst for types with DatatypeContexts. Add contex to scontext.
- default (type1 , ... , typen) ignore
gendecl -> vars :: [context =>] typeCheck type. Add to context
context -> class | ( class1 , ... , classn )Check types in class1 ... Add to context
exp -> exp0 :: [context =>] typeCheck type. Add to context
Explicit forall RankNTypes, Imporedicative types. For all free variables in
Eq (...)to the context where the variable is bound e.g.
Maybe ( forall b. ( forall c. HasEq (a,b,c,forall d.d) ) -> () ) -> a
Eq (a,b',c',d') => Maybe ( forall b. (Eq (a,b,c'',d'')) => ( forall c. (Eq (a,b,c,d''')) => HasEq (a,b,c,forall d.d) ) -> () ) -> a
Type families: like with type synonyms contexts can be safely ignored here. What about newtype type families?
Functional Dependencies: TODO
- Functions in modules without this extension. Maybe it's possible to add the contexts when the functions are imported. I don't know.