| Safe Haskell | None |
|---|---|
| Language | Haskell2010 |
Data.ZipMatchK.TH
Description
Template Haskell derivation of ZipMatchK instances.
The generic instance (the one obtained by writing instance ZipMatchK TermSig
with no body) converts a node into its Generics.Kind representation on
every comparison, and converts the result back. The representation of a
constructor is a chain of L1/R1 wrappers as long as that constructor's
index, so the cost grows with the number of constructors in the signature,
and comparing terms is most of what a typechecker does.
The derivers here generate the instance that one would otherwise write out
by hand: a case over the two nodes, allocating only its result. On a large
signature that is worth roughly a factor of two in time and in allocation on
alphaEquiv (see the zipmatchk benchmark), and
unlike the generic instance the derived one does not get slower as the
signature grows.
The module the splice appears in needs at least
{-# LANGUAGE GADTs #-}
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE TypeFamilies #-}Signatures that refer to one another have to be derived in a __single
splice__, since a top-level splice ends a declaration group and an instance
from a later group is not visible to an earlier one. The signatures that
mkFreeFoil generates from a grammar
with several syntactic categories are of that kind:
concat <$> traverse deriveZipMatchK2 [''Term'Sig, ''OpArg'Sig, ''Type'Sig]
Synopsis
- deriveZipMatchK :: Name -> Q [Dec]
- deriveZipMatchK1 :: Name -> Q [Dec]
- deriveZipMatchK2 :: Name -> Q [Dec]
- deriveZipMatchKWith :: Maybe Int -> Name -> Q [Dec]
Documentation
deriveZipMatchK :: Name -> Q [Dec] Source #
Derive a ZipMatchK instance, zipping all type parameters.
For a signature bifunctor
data TermSig scope term = AppSig term term | LamSig scope deriveZipMatchK ''TermSig
this generates
instance ZipMatchK TermSig where
zipMatchWithK (f :^: g :^: M0) x y = case (x, y) of
(AppSig l1 l2, AppSig r1 r2) -> AppSig <$> g l1 r1 <*> g l2 r2
(LamSig l1, LamSig r1) -> LamSig <$> f l1 r1
_ -> NothingUse deriveZipMatchK2 when the type has extra parameters that should stay
fixed (an annotation, say), as a signature generated by
Control.Monad.Free.Foil.TH.MkFreeFoil does.
Since: 0.3.2
deriveZipMatchK1 :: Name -> Q [Dec] Source #
Derive a ZipMatchK instance for a functor, zipping the last type parameter
and fixing the rest.
Since: 0.3.2
deriveZipMatchK2 :: Name -> Q [Dec] Source #
Derive a ZipMatchK instance for a signature bifunctor, zipping the last two
type parameters (the scoped terms and the terms) and fixing the rest.
For a signature with an extra parameter (a source position, for instance)
data Term'Sig a scope term = AppSig a term term | LamSig a scope deriveZipMatchK2 ''Term'Sig
this generates
instance ZipMatchK a => ZipMatchK (Term'Sig a) where
zipMatchWithK (f :^: g :^: M0) x y = case (x, y) of
(AppSig l1 l2 l3, AppSig r1 r2 r3) ->
AppSig <$> zipMatchWithK M0 l1 r1 <*> g l2 r2 <*> g l3 r3
...Since: 0.3.2