emilaxelsson / syntactic

Generic representation and manipulation of abstract syntax
BSD 3-Clause "New" or "Revised" License
25 stars 13 forks source link

Default instances for EvalEnv #20

Closed crockeea closed 9 years ago

crockeea commented 9 years ago

I see in the docs that there is support for default instances of several classes, but I don't know of any way to avoid writing manual EvalEnv instances.

For every domain Dom, my instances look like:

data Dom a where
  A :: i -> Dom (Full a)
  B :: Dom (Full a)
  ...

instance EvalEnv Dom env where
  compileSym p x@(A _) = compileSymDefault p x
  compileSym p x@B = compileSymDefault p x
  ...

It'd be very convenient to not have to write this boilerplate for every domain.

emilaxelsson commented 9 years ago

If you just had compileSym p x = compileSymDefault p x then it could be handled by DefaultSignatures, but the problem is that you need to match on the constructors in order to provide the Signature constraint.

The only option I can see is to introduce a new class

class Symbol sym
  where
    symbolSignature :: sym sig -> Dict (Signature sig)
    -- Or alternatively:
    -- symbolSignature :: s sig -> SigRep sig

With this class, you wouldn't have to state the obvious in the EvalEnv instance. Instead you'd have to do it when you instantiate Symbol:

instance Symbol Dom
  where
    symbolSignature (A _) = Dict
    symbolSignature B     = Dict

Since there are potentially other classes than EvalEnv that could benefit from this, it might be worth the trouble. Of course, it is also easy to generate Symbol instances using TemplateHaskell.