Portability | ghc |
---|---|
Stability | unstable |
Maintainer | Andy Gill <andygill@ku.edu> |
This module contains a Template Haskell based generator for the many data-type specific functions that KURE want users to write. KURE Your Boilerplate (KYB) attempts to make writing these function easy. Eventually, there will be a small DSL for effects inside the generated functions.
Unfortunately, you still need to write the Term
instance by hand, because of the use of
type families, a feature that post-dates Template Haskell. You also need to write
the single MyGeneric datatype, which is considered documentation of what you want
KYB to do.
kureYourBoilerplate
generates a Walker
instance for every data-type mentioned in your Generic,
a Walker
instance for the Generic type itself,
and the following for every constructor in every data-structure that is mentioned in Generic.
For exmaple if a constructor is called Foo
, and has type Foo :: A -> B -> C
, we generate
-
fooR :: (...) => R A -> R B -> R C --
congruence overFoo
. -
fooU :: (...,Monoid r) => T A r -> T B r -> T C r --
unify the interesting arguments of aFoo
. -
fooG :: (...) => R C --
guard for the constructorFoo
. -
fooP :: (...) => (A -> B -> T C a) -> T C a --
pattern matching onFoo
. -
withFoo :: (...,Failable f) => (A -> B -> f a) -> C -> f a --
application and pattern matching onFoo
.
Here, R is short for a 'Rewrite m dec', and 'T is short for 'Translate m dec'.
An example of use is
$(kureYourBoilerplate ''MyGeneric [(''Id,''())])
Which means MyGeneric
is my universal type, Id
is my monad, and ()
is my monoid.
Documentation
kureYourBoilerplate :: Name -> [(Name, Name)] -> Q [Dec]Source
kureYourBoilerplate
generates a number of functions for each data-type mentioned in
our given Generic data-type, which we need to provide for KURE, as well as the
Walker instance.
The first argument is the name of the Generic data-structure, which you need to write by hand. If you provide the name of a type synonym as the first argument, then KYB assumes that you are acting over a single data-type, i.e. you generic is your AST type. If you provide the name of a data-type (the typical use-case), then this function generates code for every conceptual sub-type of the provided data-type.
The second argument is the monad over which you will be parameterizing your rewrite rules, and the third argument is the monoid over which you will be parameterizing.