2024-10-05 13:31:09 -07:00
|
|
|
{-# LANGUAGE GADTs #-}
|
|
|
|
|
|
|
|
|
|
module Expr where
|
|
|
|
|
|
|
|
|
|
import Data.Function (on)
|
2024-10-06 14:02:35 -07:00
|
|
|
import Data.List (genericDrop)
|
2024-10-05 13:31:09 -07:00
|
|
|
|
|
|
|
|
data Expr where
|
2024-10-06 14:02:35 -07:00
|
|
|
Var :: Integer -> Expr
|
|
|
|
|
Star :: Expr
|
|
|
|
|
Square :: Expr
|
|
|
|
|
App :: Expr -> Expr -> Expr
|
|
|
|
|
Abs :: Expr -> Expr -> Expr
|
|
|
|
|
Pi :: Expr -> Expr -> Expr
|
|
|
|
|
deriving (Show, Eq)
|
|
|
|
|
|
2024-11-11 13:43:28 -08:00
|
|
|
occursFree :: Integer -> Expr -> Bool
|
|
|
|
|
occursFree n (Var k) = n == k
|
|
|
|
|
occursFree _ Star = False
|
|
|
|
|
occursFree _ Square = False
|
|
|
|
|
occursFree n (App a b) = occursFree n a || occursFree n b
|
|
|
|
|
occursFree n (Abs a b) = occursFree n a || occursFree (n + 1) b
|
|
|
|
|
occursFree n (Pi a b) = occursFree n a || occursFree (n + 1) b
|
|
|
|
|
|
2024-10-06 14:02:35 -07:00
|
|
|
{- --------------------- PRETTY PRINTING ----------------------------- -}
|
|
|
|
|
|
|
|
|
|
-- TODO : store parsed identifiers for better printing
|
|
|
|
|
genName :: Integer -> String
|
|
|
|
|
genName k = case genericDrop k ["x", "y", "z", "w", "u", "v"] of
|
|
|
|
|
[] -> 'x' : show (k - 6)
|
|
|
|
|
(v : _) -> v
|
|
|
|
|
|
|
|
|
|
pretty :: Expr -> String
|
|
|
|
|
pretty = helper 0
|
|
|
|
|
where
|
|
|
|
|
helper :: Integer -> Expr -> String
|
|
|
|
|
helper k (Var n) = genName $ k - n - 1
|
|
|
|
|
helper _ Star = "*"
|
|
|
|
|
helper _ Square = "□"
|
|
|
|
|
helper k (App e1 e2) = "(" ++ helper k e1 ++ " " ++ helper k e2 ++ ")"
|
|
|
|
|
helper k (Abs ty b) =
|
|
|
|
|
"(λ" ++ genName k ++ " : " ++ helper k ty ++ " . " ++ helper (k + 1) b ++ ")"
|
|
|
|
|
helper k (Pi ty b) =
|
2024-11-11 13:43:28 -08:00
|
|
|
if occursFree 0 b
|
|
|
|
|
then
|
|
|
|
|
"(∏" ++ genName k ++ " : " ++ helper k ty ++ " . " ++ helper (k + 1) b ++ ")"
|
|
|
|
|
else "(" ++ helper k ty ++ " -> " ++ helper (k + 1) b ++ ")"
|
2024-10-06 14:02:35 -07:00
|
|
|
|
|
|
|
|
{- --------------- ACTUAL MATH STUFF ---------------- -}
|
2024-10-05 13:31:09 -07:00
|
|
|
|
|
|
|
|
isSort :: Expr -> Bool
|
|
|
|
|
isSort Star = True
|
|
|
|
|
isSort Square = True
|
|
|
|
|
isSort _ = False
|
|
|
|
|
|
|
|
|
|
mapIndices :: (Integer -> Expr) -> Expr -> Expr
|
|
|
|
|
mapIndices f (Var n) = f n
|
|
|
|
|
mapIndices _ Star = Star
|
|
|
|
|
mapIndices _ Square = Square
|
|
|
|
|
mapIndices f (App m n) = App (mapIndices f m) (mapIndices f n)
|
|
|
|
|
mapIndices f (Abs m n) = Abs (mapIndices f m) (mapIndices f n)
|
|
|
|
|
mapIndices f (Pi m n) = Pi (mapIndices f m) (mapIndices f n)
|
|
|
|
|
|
|
|
|
|
incIndices :: Expr -> Expr
|
|
|
|
|
incIndices = mapIndices (Var . (+ 1))
|
|
|
|
|
|
|
|
|
|
decIndices :: Expr -> Expr
|
|
|
|
|
decIndices = mapIndices (Var . subtract 1)
|
|
|
|
|
|
2024-11-11 13:37:44 -08:00
|
|
|
-- substitute 0 for s *AND* decrement indices; only use after reducing a redex.
|
|
|
|
|
subst :: Expr -> Expr -> Expr
|
|
|
|
|
subst s (Var 0) = s
|
|
|
|
|
subst _ (Var n) = Var $ n - 1
|
|
|
|
|
subst _ Star = Star
|
|
|
|
|
subst _ Square = Square
|
|
|
|
|
subst s (App m n) = App (subst s m) (subst s n)
|
|
|
|
|
subst s (Abs m n) = Abs (subst s m) (subst s n)
|
|
|
|
|
subst s (Pi m n) = Pi (subst s m) (subst s n)
|
|
|
|
|
|
|
|
|
|
substnd :: Expr -> Expr -> Expr
|
|
|
|
|
substnd s (Var n) = if n == 0 then s else Var n
|
|
|
|
|
substnd _ Star = Star
|
|
|
|
|
substnd _ Square = Square
|
|
|
|
|
substnd s (App m n) = App (substnd s m) (substnd s n)
|
|
|
|
|
substnd s (Abs m n) = Abs (substnd s m) (substnd s n)
|
|
|
|
|
substnd s (Pi m n) = Pi (substnd s m) (substnd s n)
|
2024-10-05 13:31:09 -07:00
|
|
|
|
|
|
|
|
betaReduce :: Expr -> Expr
|
|
|
|
|
betaReduce (Var k) = Var k
|
|
|
|
|
betaReduce Star = Star
|
|
|
|
|
betaReduce Square = Square
|
2024-11-11 13:37:44 -08:00
|
|
|
betaReduce (App (Abs _ v) n) = subst n v
|
2024-10-05 13:31:09 -07:00
|
|
|
betaReduce (App m n) = App (betaReduce m) (betaReduce n)
|
|
|
|
|
betaReduce (Abs t v) = Abs (betaReduce t) (betaReduce v)
|
|
|
|
|
betaReduce (Pi t v) = Pi (betaReduce t) (betaReduce v)
|
|
|
|
|
|
|
|
|
|
betaNF :: Expr -> Expr
|
|
|
|
|
betaNF e = if e == e' then e else betaNF e'
|
|
|
|
|
where
|
|
|
|
|
e' = betaReduce e
|
|
|
|
|
|
|
|
|
|
betaEquiv :: Expr -> Expr -> Bool
|
|
|
|
|
betaEquiv = on (==) betaNF
|