{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE EmptyDataDecls #-}
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE OverlappingInstances #-}
import Generics.Instant
import Generics.Instant.TH
import Generics.Instant.Functions
import Prelude hiding (Eq, Show(..))
import qualified Prelude as P (Show(..))
-------------------------------------------------------------------------------
-- Simple Datatype
-------------------------------------------------------------------------------
-- Example datatype
data Exp = Const Int | Plus Exp Exp
data Const
data Plus
instance Constructor Const where conName _ = "Const"
instance Constructor Plus where conName _ = "Plus"
-- Representable instance
instance Representable Exp where
type Rep Exp = C Const (Var Int) :+: C Plus (Rec Exp :*: Rec Exp)
from (Const n) = L (C (Var n))
from (Plus e e') = R (C (Rec e :*: Rec e'))
to (L (C (Var n))) = Const n
to (R (C (Rec e :*: Rec e'))) = Plus e e'
exp1 = Plus (Const 1) (Const 2)
exp2 = Plus exp1 (Const 3)
instance Eq Exp where eq' = eq
testExp1 :: (Bool, Bool)
testExp1 = (eq exp2 exp2, eq exp1 exp2)
instance Empty Exp where empty' = empty
testExp2 :: Exp
testExp2 = empty
instance Show Exp where show' = show
instance P.Show Exp where show = show -- convenience
testExp3 :: String
testExp3 = show exp2
{-
instance Update Exp where update' = update
instance MapOn Int where mapOn = (+1)
testExp4 :: Exp
testExp4 = update exp2
-}
-------------------------------------------------------------------------------
-- Mutually recursive datatypes
-------------------------------------------------------------------------------
data Decl = None | Seq Decl Decl | Assign String Expr
data Expr = V String | Lam String Expr | App Expr Expr | Let Decl Expr
{-
data None
data Seq
data Assign
data V
data Lam
data App
data Let
instance Constructor None where conName _ = "None"
instance Constructor Seq where conName _ = "Seq"
instance Constructor Assign where conName _ = "Assign"
instance Constructor V where conName _ = "V"
instance Constructor Lam where conName _ = "Lam"
instance Constructor App where conName _ = "App"
instance Constructor Let where conName _ = "Let"
instance Representable Decl where
type Rep Decl = C None U
:+: C Seq (Rec Decl :*: Rec Decl)
:+: C Assign (Var String :*: Rec Expr)
from None = L (C U)
from (Seq d1 d2) = R (L (C (Rec d1 :*: Rec d2)))
from (Assign v e) = R (R (C (Var v :*: Rec e)))
to (L (C U)) = None
to (R (L (C (Rec d1 :*: Rec d2)))) = Seq d1 d2
to (R (R (C (Var v :*: Rec e)))) = Assign v e
instance Representable Expr where
type Rep Expr = C V (Var String)
:+: C Lam (Var String :*: Rec Expr)
:+: C App (Rec Expr :*: Rec Expr)
:+: C Let (Rec Decl :*: Rec Expr)
from (V x) = L (C (Var x))
from (Lam v e) = R (L (C (Var v :*: Rec e)))
from (App f e) = R (R (L (C (Rec f :*: Rec e))))
from (Let d e) = R (R (R (C (Rec d :*: Rec e))))
to (L (C (Var x))) = V x
to (R (L (C (Var v :*: Rec e)))) = Lam v e
to (R (R (L (C (Rec f :*: Rec e))))) = App f e
to (R (R (R (C (Rec d :*: Rec e))))) = Let d e
-}
-- Using TH instead
$(deriveAll ''Decl)
$(deriveAll ''Expr)
decls = Seq (Assign "x" (Lam "z" (V "z"))) (Assign "y" (V "x"))
expr = Let decls (App (V "x") (V "y"))
instance Show Expr where show' = show
instance Show Decl where show' = show
instance P.Show Expr where show = show -- convenience
instance P.Show Decl where show = show -- convenience
testAST1 :: String
testAST1 = show expr
instance Empty Expr where empty' = empty
instance Empty Decl where empty' = empty
testAST2 :: Expr
testAST2 = empty
testAST3 :: Decl
testAST3 = empty
instance Eq Expr where eq' = eq
instance Eq Decl where eq' = eq
testAST4 :: Bool
testAST4 = eq expr expr
{-
instance Update Decl where update' = update
instance Update Expr where update' = update
instance MapOn [Char] where mapOn _ = "a"
testAST5 :: Decl
testAST5 = update decls
testAST6 :: Expr
testAST6 = update expr
-}