Based off of the paper "A Pattern for Almost Homomorphic Functions"
at http://www.ittc.ku.edu/~nfrisby/frisby-wgp-2012.pdf, presented at the
Workshop on Generic Programming 2012. Also, my
dissertation http://www.ittc.ku.edu/~nfrisby/frisby-dissertation.pdf
yoko views a nominal datatype as a band of constructors, each
a nominal type in its own right. Such datatypes can be disbanded via the
disband function into an anonymous sum of nominal constructors, and vice
versa via the band function. This library uses extensive type-level
programming to enrich its instant-generics foundation with capabilities
derived from the constructor-centric perspective.
For example, consider the following nominal datatype.
This type can of course be understood as a sum of the individual
fields types.
yoko's conceptual foundations start there. In particular, this allows a
constructor, say John, to be used independently of its original range type
and sibling constructors.
As a generic programming library, yoko extends instant-generics with
support for constructor-centric generic programming. The
Examples/LambdaLift/LambdaLift.hs file distributed with the yoko source
demonstrates defining a lambda-lifting conversion between the two types
ULC, which has lambdas, and Prog, which has top-level function
declarations instead.
These types are defined in separate modules, since they have constructors
with the same name. Indeed, the fact that they having matching constructors
named App is crucial for yoko's automatic conversion from ULC's App
to TLF's App. As written, the generic lambda-lifter would continue to
work for any new ULC constructors (e.g. syntax for tuples or mutable
references) as long as constructors with the same names and analogous fields
were added to TLF and the semantics of those constructors doesn't involve
binding. This default generic behavior of the lambda-lifter is specified in
about ten lines of user code.
The non-generic code is much more complicated. This is intentional: I wanted
to show that sometimes shoehorning an algorithm into the requisite type (ie
a -> m a') can be difficult and require subtleties like backwards state.
Existing generic libraries don't use constructor names to the degree that
yoko does, and so cannot accomodate generic conversions as well.