2024-10-05 13:31:09 -07:00
|
|
|
{-# LANGUAGE GADTs #-}
|
|
|
|
|
|
|
|
|
|
module Expr where
|
|
|
|
|
|
|
|
|
|
import Data.Function (on)
|
|
|
|
|
|
|
|
|
|
data Expr where
|
2024-11-11 14:10:27 -08:00
|
|
|
Var :: Integer -> String -> Expr
|
2024-10-06 14:02:35 -07:00
|
|
|
Star :: Expr
|
|
|
|
|
Square :: Expr
|
|
|
|
|
App :: Expr -> Expr -> Expr
|
2024-11-11 14:10:27 -08:00
|
|
|
Abs :: String -> Expr -> Expr -> Expr
|
|
|
|
|
Pi :: String -> Expr -> Expr -> Expr
|
2024-10-06 14:02:35 -07:00
|
|
|
deriving (Show, Eq)
|
|
|
|
|
|
2024-11-11 16:38:46 -08:00
|
|
|
infixl 4 <.>
|
|
|
|
|
|
|
|
|
|
(<.>) :: Expr -> Expr -> Expr
|
|
|
|
|
(<.>) = App
|
|
|
|
|
|
|
|
|
|
infixr 2 .->
|
|
|
|
|
|
|
|
|
|
(.->) :: Expr -> Expr -> Expr
|
|
|
|
|
a .-> b = Pi "" a (incIndices b)
|
|
|
|
|
|
2024-11-11 13:43:28 -08:00
|
|
|
occursFree :: Integer -> Expr -> Bool
|
2024-11-11 14:10:27 -08:00
|
|
|
occursFree n (Var k _) = n == k
|
2024-11-11 13:43:28 -08:00
|
|
|
occursFree _ Star = False
|
|
|
|
|
occursFree _ Square = False
|
2024-11-11 13:52:50 -08:00
|
|
|
occursFree n (App a b) = on (||) (occursFree n) a b
|
2024-11-11 14:10:27 -08:00
|
|
|
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-11-11 13:43:28 -08:00
|
|
|
|
2024-10-06 14:02:35 -07:00
|
|
|
{- --------------------- PRETTY PRINTING ----------------------------- -}
|
|
|
|
|
|
2024-11-11 14:34:55 -08:00
|
|
|
parenthesize :: String -> String
|
|
|
|
|
parenthesize s = "(" ++ s ++ ")"
|
|
|
|
|
|
2024-11-11 16:38:46 -08:00
|
|
|
collectLambdas :: Expr -> ([(String, Expr)], Expr)
|
|
|
|
|
collectLambdas (Abs x ty body) = ((x, ty) : params, final)
|
|
|
|
|
where
|
|
|
|
|
(params, final) = collectLambdas body
|
|
|
|
|
collectLambdas e = ([], e)
|
|
|
|
|
|
|
|
|
|
collectPis :: Expr -> ([(String, Expr)], Expr)
|
|
|
|
|
collectPis p@(Pi "" _ _) = ([], p)
|
|
|
|
|
collectPis (Pi x ty body) = ((x, ty) : params, final)
|
|
|
|
|
where
|
|
|
|
|
(params, final) = collectPis body
|
|
|
|
|
collectPis e = ([], e)
|
|
|
|
|
|
|
|
|
|
groupParams :: [(String, Expr)] -> [([String], Expr)]
|
|
|
|
|
groupParams = foldr addParam []
|
|
|
|
|
where
|
|
|
|
|
addParam :: (String, Expr) -> [([String], Expr)] -> [([String], Expr)]
|
|
|
|
|
addParam (x, t) [] = [([x], t)]
|
|
|
|
|
addParam (x, t) l@((xs, s) : rest)
|
|
|
|
|
| t == s = (x : xs, t) : rest
|
|
|
|
|
| otherwise = ([x], t) : l
|
|
|
|
|
|
|
|
|
|
showParamGroup :: ([String], Expr) -> String
|
|
|
|
|
showParamGroup (ids, ty) = parenthesize $ unwords ids ++ " : " ++ pretty ty
|
|
|
|
|
|
2024-11-11 14:34:55 -08:00
|
|
|
helper :: Integer -> Expr -> String
|
|
|
|
|
helper _ (Var _ s) = s
|
|
|
|
|
helper _ Star = "*"
|
|
|
|
|
helper _ Square = "□"
|
2024-11-11 16:38:46 -08:00
|
|
|
helper k (App e1 e2) = if k > 3 then parenthesize res else res
|
2024-11-11 14:34:55 -08:00
|
|
|
where
|
|
|
|
|
res = helper 3 e1 ++ " " ++ helper 4 e2
|
2024-11-11 16:38:46 -08:00
|
|
|
helper k (Pi "" t1 t2) = if k > 2 then parenthesize res else res
|
|
|
|
|
where
|
|
|
|
|
res = helper 3 t1 ++ " -> " ++ helper 2 t2
|
|
|
|
|
helper k e@(Pi{}) = if k > 2 then parenthesize res else res
|
2024-11-11 14:34:55 -08:00
|
|
|
where
|
2024-11-11 16:38:46 -08:00
|
|
|
(params, body) = collectPis e
|
|
|
|
|
grouped = showParamGroup <$> groupParams params
|
|
|
|
|
res = "∏ " ++ unwords grouped ++ " . " ++ pretty body
|
|
|
|
|
helper k e@(Abs{}) = if k >= 1 then parenthesize res else res
|
2024-11-11 14:34:55 -08:00
|
|
|
where
|
2024-11-11 16:38:46 -08:00
|
|
|
(params, body) = collectLambdas e
|
|
|
|
|
grouped = showParamGroup <$> groupParams params
|
|
|
|
|
res = "λ " ++ unwords grouped ++ " . " ++ pretty body
|
2024-11-11 14:34:55 -08:00
|
|
|
|
2024-10-06 14:02:35 -07:00
|
|
|
pretty :: Expr -> String
|
2024-11-11 14:34:55 -08:00
|
|
|
pretty = helper 0
|
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
|
|
|
|
|
|
|
|
|
|
incIndices :: Expr -> Expr
|
2024-11-11 14:10:27 -08:00
|
|
|
incIndices (Var n x) = Var (n + 1) x
|
|
|
|
|
incIndices Star = Star
|
|
|
|
|
incIndices Square = Square
|
|
|
|
|
incIndices (App m n) = App (incIndices m) (incIndices n)
|
|
|
|
|
incIndices (Abs x m n) = Abs x (incIndices m) (incIndices n)
|
|
|
|
|
incIndices (Pi x m n) = Pi x (incIndices m) (incIndices n)
|
2024-10-05 13:31:09 -07:00
|
|
|
|
2024-11-11 13:52:50 -08:00
|
|
|
-- substitute s for 0 *AND* decrement indices; only use after reducing a redex.
|
2024-11-11 13:37:44 -08:00
|
|
|
subst :: Expr -> Expr -> Expr
|
2024-11-11 14:10:27 -08:00
|
|
|
subst s (Var 0 _) = s
|
|
|
|
|
subst _ (Var n s) = Var (n - 1) s
|
2024-11-11 13:37:44 -08:00
|
|
|
subst _ Star = Star
|
|
|
|
|
subst _ Square = Square
|
|
|
|
|
subst s (App m n) = App (subst s m) (subst s n)
|
2024-11-11 14:10:27 -08:00
|
|
|
subst s (Abs x m n) = Abs x (subst s m) (subst s n)
|
|
|
|
|
subst s (Pi x m n) = Pi x (subst s m) (subst s n)
|
2024-11-11 13:37:44 -08:00
|
|
|
|
|
|
|
|
substnd :: Expr -> Expr -> Expr
|
2024-11-11 14:10:27 -08:00
|
|
|
substnd s (Var 0 _) = s
|
|
|
|
|
substnd _ (Var n s) = Var (n - 1) s
|
2024-11-11 13:37:44 -08:00
|
|
|
substnd _ Star = Star
|
|
|
|
|
substnd _ Square = Square
|
|
|
|
|
substnd s (App m n) = App (substnd s m) (substnd s n)
|
2024-11-11 14:10:27 -08:00
|
|
|
substnd s (Abs x m n) = Abs x (substnd s m) (substnd s n)
|
|
|
|
|
substnd s (Pi x m n) = Pi x (substnd s m) (substnd s n)
|
2024-10-05 13:31:09 -07:00
|
|
|
|
|
|
|
|
betaReduce :: Expr -> Expr
|
2024-11-11 14:10:27 -08:00
|
|
|
betaReduce (Var k s) = Var k s
|
2024-10-05 13:31:09 -07:00
|
|
|
betaReduce Star = Star
|
|
|
|
|
betaReduce Square = Square
|
2024-11-11 14:10:27 -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)
|
2024-11-11 14:10:27 -08:00
|
|
|
betaReduce (Abs x t v) = Abs x (betaReduce t) (betaReduce v)
|
|
|
|
|
betaReduce (Pi x t v) = Pi x (betaReduce t) (betaReduce v)
|
2024-10-05 13:31:09 -07:00
|
|
|
|
|
|
|
|
betaNF :: Expr -> Expr
|
|
|
|
|
betaNF e = if e == e' then e else betaNF e'
|
|
|
|
|
where
|
|
|
|
|
e' = betaReduce e
|
|
|
|
|
|
|
|
|
|
betaEquiv :: Expr -> Expr -> Bool
|
|
|
|
|
betaEquiv = on (==) betaNF
|