| Safe Haskell | Safe-Inferred |
|---|---|
| Language | Haskell2010 |
Kanren.TH
Description
Automatic generation of logic types.
Synopsis
- makeLogical :: Name -> Q [Dec]
- makeLogicals :: [Name] -> Q [Dec]
- makeLogicType :: Name -> Q [Dec]
- makeLogicTypes :: [Name] -> Q [Dec]
- data LogicTypeRules
- defaultLogicTypeRules :: LogicTypeRules
- makeLogicTypeWith :: LogicTypeRules -> Name -> Q [Dec]
- makeLogicTypesWith :: LogicTypeRules -> [Name] -> Q [Dec]
- makeLogicalInstance :: Name -> Name -> Q [Dec]
- makeLogicalInstances :: [(Name, Name)] -> Q [Dec]
- makeExhaustivePrisms :: Name -> Q [Dec]
Documentation
makeLogical :: Name -> Q [Dec] Source #
Generate a logic representation and a corresponding Logical instance for
a given type.
Using this function requires you to enable the DeriveGeneric and
TypeFamilies extensions.
Consider the following type definition:
data Tree a = Empty | Leaf a | Tree a :* Tree a
makeLogical ''Tree yields
data LogicTree a = LogicEmpty | LogicLeaf (Term a) | Term (Tree a) :?* Term (Tree a) deriving (Generic) instance Logical a => Logical (Tree a) where type Logic (Tree a) = LogicTree a unify = genericUnify walk = genericWalk occursCheck = genericOccursCheck inject = genericInject extract = genericExtract
For details, see makeLogicType and makeLogicalInstance.
makeLogicals :: [Name] -> Q [Dec] Source #
Generate a logic representation and a corresponding Logical instance for
each given type. This works like makeLogical, but better suits mutually
recursive types.
Logic representations
makeLogicType :: Name -> Q [Dec] Source #
Generate a logic representation for a given type.
Consider the following type definition:
data Tree a = Empty | Leaf a | Tree a :* Tree a
makeLogicType ''Tree yields
data LogicTree a = LogicEmpty | LogicLeaf (Term a) | Term (Tree a) :?* Term (Tree a)
For newtypes, it doesn't make sense to introduce another layer of
variables. Hence, Logic will be used instead of Term.
newtype BetterInt = BetterInt Int makeLogicType ''BetterInt -- ^ newtype LogicBetterInt = LogicBetterInt (Logic Int)
makeLogicTypes :: [Name] -> Q [Dec] Source #
Generate a logic representation for several types. This works like
makeLogicType, but better suits mutually recursive types.
data LogicTypeRules Source #
Settings for generating a type's logic representation.
defaultLogicTypeRules :: LogicTypeRules Source #
Default LogicTypeRules. Does not derive any instances for the logical
representation.
makeLogicTypeWith :: LogicTypeRules -> Name -> Q [Dec] Source #
makeLogicType, but allows configuring how the logical representation is
generated.
makeLogicTypesWith :: LogicTypeRules -> [Name] -> Q [Dec] Source #
makeLogicTypes, but allows configuring how the logical representations
are generated.
Logical instances
makeLogicalInstance :: Name -> Name -> Q [Dec] Source #
Generate a Logical instance, given a type and its logical representation.
Currently, the instance relies on GenericLogical, so both types need to
have a Generic instance. When using makeLogical, the logical
representation will have a derived Generic instance.
For each type variable, there will be a Logical constraint.
Since Logical includes a type family definition, using this function
requires enabling the TypeFamilies extension.
Consider the following declarations:
data Tree a = Empty | Leaf a | Tree a :* Tree a deriving (Generic) makeLogicType ''Tree deriving instance Generic (LogicTree a)
makeLogicalInstance ''Tree ''LogicTree yields
instance Logical a => Logical (Tree a) where type Logic (Tree a) = LogicTree a unify = genericUnify walk = genericWalk occursCheck = genericOccursCheck inject = genericInject extract = genericExtract
makeLogicalInstances :: [(Name, Name)] -> Q [Dec] Source #
Generate Logical instances, given pairs of a type and its logical
representation. This works like makeLogicalInstance, but better suits
mutually recursive types.
Exhaustive prisms
makeExhaustivePrisms :: Name -> Q [Dec] Source #
Generate ExhaustivePrisms for a given (supposedly logic) type.
This function expects that you already have regular prisms in the scope whose
names are constructor names prefixed with _ (i.e. you used
makePrisms). Then, exhaustive prisms will have a prime in
the end (or an exclamation mark for infix constructors).
Consider the following declarations:
data Tree a = Empty | Leaf a | Tree a :* Tree a deriving (Generic) makeLogicType ''Tree makePrisms ''LogicTree
makeExhaustivePrisms ''LogicTree yields (sans short tags)
_LogicEmpty' :: ExhaustivePrism (LogicTree a) (e, l, n) (e', l, n) () e e' _LogicEmpty' = from _Tagged . _LogicEmpty . _Tagged _LogicLeaf' :: ExhaustivePrism (LogicTree a) (e, l, n) (e, l', n) (Term a) l l' _LogicLeaf' = from _Tagged . _LogicLeaf . _Tagged (.:?*!) :: ExhaustivePrism (LogicTree a) (e, l, n) (e, l, n') (Term (Tree a), Term (Tree a)) n n' (.:?*!) = from _Tagged . (.:?*) . _Tagged