| Portability | non-portable |
|---|---|
| Stability | experimental |
| Maintainer | generics@haskell.org |
| Safe Haskell | Safe-Infered |
Generics.Regular.Rewriting
Description
By importing this module, the user is able to use all the rewriting
machinery. The user is only required to provide an instance of
Regular and Rewrite for the datatype.
Consider a datatype representing logical propositions:
data Expr = Const Int | Expr :++: Expr | Expr :**: Expr deriving Show infixr 5 :++: infixr 6 :**:
An instance of Regular would look like:
data Const
data Plus
data Times
instance Constructor Const where conName _ = "Const"
instance Constructor Plus where
conName _ = "(:++:)"
conFixity _ = Infix RightAssociative 5
instance Constructor Times where
conName _ = "(:**:)"
conFixity _ = Infix RightAssociative 6
type instance PF Expr = C Const (K Int)
:+: C Plus (I :*: I)
:+: C Times (I :*: I)
instance Regular Expr where
from (Const n) = L (C (K n))
from (e1 :++: e2) = R (L (C $ (I e1) :*: (I e2)))
from (e1 :**: e2) = R (R (C $ (I e1) :*: (I e2)))
to (L (C (K n))) = Const n
to (R (L (C ((I r1) :*: (I r2))))) = r1 :++: r2
to (R (R (C ((I r1) :*: (I r2))))) = r1 :**: r2
Alternatively, the above code could be derived using Template Haskell:
$(deriveConstructors ''Expr) $(deriveRegular ''Expr "PFExpr") type instance PF Expr = PFExpr
Additionally, the instance Rewrite would look like:
instance Rewrite Expr
Rules are built like this:
rule1 :: Rule Expr
rule1 =
rule $ \x -> x :++: Const 0 :~>
x
rule5 :: Rule Expr
rule5 =
rule $ \x y z -> x :**: (y :++: z) :~>
(x :**: y) :++: (x :**: z)
And applied as follows:
test1 :: Maybe Expr test1 = rewriteM rule1 (Const 2 :++: Const 0) test10 :: Maybe Expr test10 = rewriteM rule5 ((Const 1) :**: ((Const 2) :++: (Const 3)))