{-# LANGUAGE DeriveDataTypeable, DeriveGeneric #-}
module TestShiftEmbed (test_shiftEmbed) where
import Prelude hiding (pi)
import Data.Typeable (Typeable)
import GHC.Generics (Generic)
import Unbound.Generics.LocallyNameless
import qualified Unbound.Generics.PermM as PermM
import AlphaAssertions
import Test.Tasty
import Test.Tasty.HUnit
type Var = Name Term
data Term
= V Var
| Pi (Bind (Var, Embed Term) Term)
| LetRec (Bind (Rec Decl) Term)
deriving (Show, Generic, Typeable)
data Decl =
-- a recursive declaration x : A = m
-- where x may occur in m but not in A
Decl {
declVar :: Var
, declClass :: Shift (Embed Term)
, declVal :: Embed Term
}
deriving (Show, Generic, Typeable)
instance Alpha Term
instance Alpha Decl
x, y, z :: Var
x = s2n "x"
y = s2n "y"
z = s2n "z"
pi :: Var -> Term -> Term -> Term
pi v a b = Pi $ bind (v, embed a) b
letrec :: Decl -> Term -> Term
letrec d e = LetRec $ bind (rec d) e
decl :: Var -> Term -> Term -> Decl
decl v klass e = Decl v (embed klass) (embed e)
test_shiftEmbed =
testGroup "Embedded and Shifted terms"
[
testGroup "Embed"
[
testCase "(pi x:x . x) = (pi y:x . y)" $ let m1 = pi x (V x) (V x)
m2 = pi y (V x) (V y)
in assertAeq m1 m2
, testCase "(letrec x : x = x in x) = (letrec y : x = y in y)"
$ let m1 = letrec (decl x (V x) (V x)) (V x)
m2 = letrec (decl y (V x) (V y)) (V y)
in assertAeq m1 m2
, testCase "pi x : z . (letrec x : x = x in x) = pi y : z . (letrec x : y = x in x)"
$ let m1 = pi x (V z) $ letrec (decl x (V x) (V x)) (V x)
m2 = pi y (V z) $ letrec (decl x (V y) (V x)) (V x)
in assertAeq m1 m2
]
]