I'm using the syntactic library to make an AST. To evaluate the AST to a (Haskell) value, all of my nodes need to be an instance of the syntactic class EvalEnv
:
class EvalEnv sym env where
compileSym :: proxy env -> sym sig -> DenotationM (Reader env) sig
Syntactic also provides a "default" implementation:
compileSymDefault :: (Eval sym, Signature sig)
=> proxy env -> sym sig -> DenotationM (Reader env) sig
but the constraint on sig
is unreachable in instances of EvalEnv
, making the following (say, overlapping) instance impossible:
instance EvalEnv sym env where
compileSym = compileSymDefault
All of my user-defined AST nodes are GADTs, usually with multiple constructors, where the a
parameter always satisfies the constraint for compileSymDefault
:
data ADDITIVE a where
Add :: (Num a) => ADDITIVE (a :-> a :-> Full a)
Sub :: (Num a) => ADDITIVE (a :-> a :-> Full a)
As a result, I found that all of my instances for EvalEnv
look like:
instance EvalEnv ADDITIVE env where
compileSym p Add = compileSymDefault p Add
compileSym p Sub = compileSymDefault p Sub
This boilerplate instance is identical for all AST nodes, and each of the GADT constructors needs to be listed separately, as the GADT constructor signature implies the compileSymDefault
constraints.
Is there any way I can avoid having to list out each constructor for every node type I make?
compileSym
. It's not necessary, and complicates that definition. – CarlcompileSymDefault
is provided by the syntactic library. There might be some reason for it there. – crockeeaAdditive
? I can't find it in any of thesyntactic
modules, and neither can Hayoo. hayoo.fh-wedel.de/?query=syntactic+Additive – Cirdec