Brad:
On 24/09/2009, at 11:59 AM, excerpts of what Brad Larsen wrote:
We then try to define an evaluator:
-- instance PolyArithExpr E where
-- constant = E
-- addP e1 e2 = E (eval e1 + eval e2) -- bzzt!
The instance definition for `addP' is not type correct:
Could not deduce (Num a) from the context ()
arising from a use of `+' at /home/blarsen/mail.lhs:42:20-36
One way to remedy this is to change the class definition of
PolyArithExpr so that `addP' has a Num constraint on `a':
class PolyArithExprFixed exp where
pae_constant :: a -> exp a
pae_add :: Num a => exp a -> exp a -> exp a
which allows us to define an evaluator:
instance PolyArithExprFixed E where
pae_constant = E
pae_add e1 e2 = E (eval e1 + eval e2)
I find this ``fix'' lacking, however: to define a new interpretation
of the EDSL, we may be forced to change the DSL definition. This is
non-modular, and seems like an instance of the expression
problem. (There may be a multiparameter type class solution for this.)
A better fix is to shift the type constraint to the class head, e.g.:
class PolyArithExprFixed exp a where
pae_constant :: a -> exp a
pae_add :: exp a -> exp a -> exp a
then:
instance PolyArithExprFixed E Integer where
...
or if you want to be more general:
instance Num n => PolyArithExprFixed E n where
...
but note that this instance precludes any other ones for
PolyArithExprFixed without allowing overlapping instances and hence
some Olegs / Olegging.
See, e.g.:
http://www.soi.city.ac.uk/~ross/papers/fop.html
(the slides link)
Ambiguity is IMHO best handled with a judicious application of type
(or data) families, but you can get surprisingly far by simply
requiring that every class member mention all type variables in the
class head. YMMV of course.
cheers
peter
_______________________________________________
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe