Safe Haskell | None |
---|---|
Language | Haskell2010 |
Builds fold declarations for a FoldFamily
.
Documentation
:: [Name] | names of the root datatypes |
-> [Name] | names of the n-ary functor classes to be used |
-> [Name] | names of datatypes declared to be atomic |
-> Q [Dec] |
Discovers the fold family and builds declarations from it to be spliced into a source file.
The fold family includes the root datatypes and the datatypes of all of their components, recursively. Datatypes declared as atomic will not be included, nor their components.
In general, the framework does not currently handle parameterized
datatypes, but applications of datatypes in Traversable
,
Bitraversable
, or Tritraversable
are treated as "transparent"
and traversed through.
The framework generates:
- a type-parameterized
Fold
record datatype. Each type parameterxxx
corresponds to a non-atomic datatypeXxx
in the fold family. Each fieldmkYyy
of theFold
corresponds to a constructorYyy
used by some datatype in the fold family. - an
idFold
record. Folding overidFold
is equivalent to applyingid
: it does nothing.idFold
is useful as a base record to build your own folds upon. - an
errFold
function to create aFold
record, with undefined fields that give a useful error message when accessed. ThemkXxx
field oferrFold "example"
is defined to containerror "example.mkXxx"
. - a
monadicFold
function that lifts aFold a b c
into aFold (m a) (m b) (m c)
. It applies the base fold monadically in a bottom-up, left-to-right way. - for each datatype
Xxx
, afoldXxx
function that applies aFold
to anXxx
value, returning a value of typexxx
.
The names Fold
, idFold
, errFold
, and monadicFold
are fixed.
They are intended to be imported qualified.
You are not expected to understand the structure of the generated code from this generic description. Generate code for your specific case and look at its Haddock documentation.
Since the discovery process can automatically collect a very large number of datatypes, and since the user doesn't usually see the spliced code, we require the user to declare what she expects so that there are no surprises. For that reason, any functor classes expected to be appear in the result must be declared, as are datatypes the user wants to treat as atomic.
There are a few other restrictions not mentioned here: if you hit any of them, the framework should output a helpful, intelligible error message when generating the declarations and before trying to splice and compile the declarations. You should see no errors from the compiler trying to compile bad generated code. If you do, that's a bug; please let us know. If the error messages are opaque, that's a bug too.
buildFoldsDryRun :: [Name] -> [Name] -> [Name] -> Q [Dec] Source
Prints onto standard output the result of running buildFolds
but doesn't splice the fold declarations.
for testing
Errors possible while building a FoldFamily
buildFoldFamilyMaybe :: [Name] -> [Name] -> [Name] -> Q Exp Source
Builds a FoldFamily
or returns an error. Spliced result is of
type Either
BuildErr
FoldFamily
.