{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE StandaloneDeriving #-}
{-# LANGUAGE EmptyDataDecls #-}
{-# LANGUAGE PatternSynonyms #-}
module Regular where
import Datatypes
import Generics.Regular hiding (right)
import Generics.Regular.Transformations.Main
import Generics.Regular.Zipper
import Control.Monad ( (>=>) )
import Data.Maybe (fromJust)
--------------------------------------------------------------------------------
-- Regular representations for the example datatypes
--------------------------------------------------------------------------------
--Trees
$(deriveAll ''Tree "PFTree")
type instance PF Tree = PFTree
-- Lists
$(deriveAll ''List "PFL")
type instance PF (List a) = PFL a
-- Something more exotic
$(deriveAll ''X "PFX")
type instance PF X = PFX
-- Example for paper
$(deriveAll ''AExpr "PFExpr")
type instance PF Expr = PFExpr
deriving instance Ord AExpr
-- Datatype patterns
pattern Var' x = In (InR (L (C (K x))))
pattern Const' x = In (InR (R (L (C (K x)))))
pattern Neg' x = In (InR (R (R (L (C (I x))))))
pattern Add' x y = In (InR (R (R (R (C (I x :*: I y))))))
pattern Ref' x = In (Ref x)
-- Path patterns
pattern End = []
pattern Neg_0 x = CR (CR (CL (CC CId))) : x
pattern Add_0 x = CR (CR (CR (CC (C1 CId (I ()))))) : x
pattern Add_1 x = CR (CR (CR (CC (C2 (I ()) CId)))) : x
{-
type instance PF Expr = K String :+: K Integer :+: I :+: I :*: I
instance Regular Expr where
from (Var s) = L (K s)
from (Const i) = R (L (K i))
from (Neg e) = R (R (L (I e)))
from (Add e1 e2) = R (R (R (I e1 :*: I e2)))
to (L (K s)) = Var s
to (R (L (K i))) = Const i
to (R (R (L (I e)))) = Neg e
to (R (R (R (I e1 :*: I e2)))) = Add e1 e2
-}
--------------------------------------------------------------------------------
-- Examples for the paper
--------------------------------------------------------------------------------
instance Transform Expr
-- Some example values
expr1 :: Expr
expr1 = Add (Const 1) (Var "a")
expr2 :: Expr
expr2 = Add (Const 1) (Neg (Var "a"))
expr3 :: Expr
expr3 = Add (Var "a") (Const 1)
explicitIns :: Maybe Expr
explicitIns = apply addNeg expr1
where addNeg :: Transformation Expr
addNeg = diff expr1 expr2
-- Testing the nicer notation for paths and expressions with references
test1 :: Fix (WithRef Expr)
test1 = Neg' (Ref' test2)
test2 :: Path Expr
test2 = Add_1 End
test3 :: Transformation Expr
test3 = [(test2, test1)]
test4 :: Bool
test4 = show test3 == show (diff expr1 expr2)
-- Deletion (expr2 => expr1)
explicitDel :: Maybe Expr
explicitDel = apply delNeg expr2
where delNeg :: Transformation Expr
delNeg = diff expr2 expr1 --[ ([1], In (Ref [1,0])) ]
-- Swapping (expr1 => expr3)
explicitSwap :: Maybe Expr
explicitSwap = apply swap' expr1
where swap' :: Transformation Expr
swap' = diff expr1 expr3 -- [ ([0], In $ Ref [1]), ([1], In $ Ref [0])]
-- Rotation
rotate1 = Add (Var "a") (Add (Var "b") (Var "c"))
rotate2 = Add (Add (Var "a") (Var "b")) (Var "c")
rotate = diff rotate1 rotate2