|
{-# LANGUAGE ViewPatterns #-}
|
|
{-# LANGUAGE DeriveAnyClass #-}
|
|
{-# LANGUAGE BlockArguments #-}
|
|
{-# LANGUAGE LambdaCase #-}
|
|
module Eval where
|
|
|
|
import Control.Exception
|
|
|
|
import qualified Data.Map.Strict as Map
|
|
import Data.Foldable
|
|
import Data.Typeable
|
|
import Data.IORef
|
|
import Data.Maybe
|
|
|
|
import GHC.Stack
|
|
|
|
import qualified Presyntax as P
|
|
import Presyntax (Formula)
|
|
|
|
import Syntax
|
|
|
|
import System.IO.Unsafe (unsafePerformIO)
|
|
|
|
import Systems
|
|
import Debug.Trace (traceShowId)
|
|
|
|
iand :: Value -> Value -> Value
|
|
iand = \case
|
|
VI1 -> id
|
|
VI0 -> const VI0
|
|
x -> \case
|
|
VI0 -> VI0
|
|
VI1 -> x
|
|
y -> VIAnd x y
|
|
|
|
ior :: Value -> Value -> Value
|
|
ior = \case
|
|
VI0 -> id
|
|
VI1 -> const VI1
|
|
x -> \case
|
|
VI1 -> VI1
|
|
VI0 -> x
|
|
y -> VIOr x y
|
|
|
|
inot :: Value -> Value
|
|
inot VI1 = VI0
|
|
inot VI0 = VI1
|
|
inot (VIOr x y) = iand (inot x) (inot y)
|
|
inot (VIAnd x y) = ior (inot x) (inot y)
|
|
inot (VINot x) = x
|
|
inot x = VINot x
|
|
|
|
(@@) :: Value -> Value -> Value
|
|
VNe hd xs @@ vl = VNe hd (PApp vl:xs)
|
|
VLam _ _ k @@ vl = k vl
|
|
VEqGlued a b @@ vl = VEqGlued (a @@ vl) (b @@ vl)
|
|
VOfSub (VPi _ _ k) phi u0 x @@ vl = VOfSub (k vl) phi (u0 @@ vl) (x @@ vl)
|
|
VSystem fs @@ vl = mapVSystem (VSystem fs) (@@ vl)
|
|
VIf (VLam s d k) c t b @@ vl = VIf (VLam s d (ap . force . k)) (c @@ vl) (t @@ vl) b where
|
|
ap (VPi _ _ r) = r vl
|
|
ap _ = error "type error when pushing application into if"
|
|
f @@ _ = error $ "\ncan't apply argument to " ++ show f
|
|
|
|
proj1 :: Value -> Value
|
|
proj1 (VPair x _) = x
|
|
proj1 (VEqGlued x y) = VEqGlued (proj1 x) (proj1 y)
|
|
proj1 (VNe s xs) = VNe s (PProj1:xs)
|
|
proj1 (VOfSub (VSigma _ d _) phi u0 x) = VOfSub d phi (proj1 u0) (proj1 x)
|
|
proj1 v@VSystem{} = mapVSystem v proj1
|
|
proj1 (VIf (VLam s d k) c t b) = VIf (VLam s d (proj1t . k)) (proj1 c) (proj1 t) b where
|
|
proj1t (VSigma _ d _) = d
|
|
proj1t _ = error "type error when pushing proj1 into if"
|
|
proj1 x = error $ "can't proj1 " ++ show x
|
|
|
|
proj2 :: Value -> Value
|
|
proj2 (VPair _ y) = y
|
|
proj2 (VEqGlued x y) = VEqGlued (proj2 x) (proj2 y)
|
|
proj2 (VNe s xs) = VNe s (PProj2:xs)
|
|
proj2 (VOfSub (VSigma _ d r) phi u0 x) =
|
|
VOfSub (r (proj1 x)) phi (proj2 u0) (proj2 x)
|
|
proj2 v@VSystem{} = mapVSystem v proj2
|
|
proj2 (VIf (VLam s d k) c t b) = VIf (VLam s d (proj2t . k)) (proj2 c) (proj2 t) b where
|
|
proj2t (VSigma _ d r) = r (VIf (VLam s VBool (const d)) (proj1 c) (proj1 t) b)
|
|
proj2t _ = error "type error when pushing proj1 into if"
|
|
proj2 x = error $ "can't proj2 " ++ show x
|
|
|
|
pathp :: Env -> Value -> Value -> Value -> Value -> Value -> Value
|
|
pathp env p x y f@(VLine _a _x _y e) i =
|
|
case reduceCube env i of
|
|
Just P.Bot -> VEqGlued (e i) x
|
|
Just P.Top -> VEqGlued (e i) y
|
|
_ -> e i
|
|
pathp env p x y (VEqGlued e e') i = VEqGlued (pathp env p x y e i) (pathp env p x y e' i)
|
|
|
|
pathp env p x y (VNe hd sp) i =
|
|
case reduceCube env i of
|
|
Just P.Bot -> VEqGlued (VNe hd (PPathP p x y i:sp)) x
|
|
Just P.Top -> VEqGlued (VNe hd (PPathP p x y i:sp)) y
|
|
_ | quote x == quote y -> VEqGlued (VNe hd (PPathP p x y i:sp)) x
|
|
_ -> VNe hd (PPathP p x y i:sp)
|
|
|
|
pathp env p x y (VOfSub _ _ _ v) i = pathp env p x y v i
|
|
pathp env p x y v@VSystem{} i = mapVSystem v (\f -> pathp env p x y f i)
|
|
pathp env p x y f i = error $ "Invalid pathP " ++ show f ++ " @@ " ++ show i
|
|
|
|
comp :: Env -> Value -> Formula -> Value -> Value -> Value
|
|
comp env a@(VLam ivar VI fam) phi u a0 = glue $ go (fam (VVar "woopsie")) phi u a0 where
|
|
stuck :: Value
|
|
stuck = VComp a (toValue phi) u a0
|
|
|
|
glue :: Value -> Value
|
|
glue = VOfSub (fam VI1) (toValue phi) (u @@ VI1)
|
|
|
|
go :: HasCallStack => Value -> Formula -> Value -> Value -> Value
|
|
go VPi{} phi u a0 =
|
|
let
|
|
dom x = let VPi _ d _ = fam x in d
|
|
rng x = let VPi _ _ r = fam x in r
|
|
|
|
ai1 = dom VI0
|
|
y' i y = fill env i (dom . inot) P.Bot (VSystem emptySystem) y
|
|
ybar i y = y' (inot i) y
|
|
in VLam "x" ai1 \arg ->
|
|
comp env
|
|
(VLam ivar VI (\i -> rng i (ybar i arg)))
|
|
phi
|
|
(VLam "i" VI \i -> mapVSystem (u @@ i) (@@ ybar i arg))
|
|
(a0 @@ ybar VI0 arg)
|
|
|
|
go VSigma{} phi u a0 =
|
|
let
|
|
dom x = let VSigma _ d _ = fam x in d
|
|
rng x = let VSigma _ d _ = fam x in d
|
|
|
|
a i = fill env i (dom . fam) phi (VLam "j" VI \v -> mapVSystem (u @@ v) proj1) (proj1 a0)
|
|
c1 = comp env (VLam ivar VI (getd . fam)) phi (VLam "i" VI \v -> mapVSystem (u @@ v) proj1) (proj1 a0)
|
|
c2 = comp env (VLam ivar VI (apr (a VI1) . fam)) phi (VLam "i" VI \v -> mapVSystem (u @@ v) proj2) (proj2 a0)
|
|
|
|
getd (VSigma _ d _) = d
|
|
apr x (VSigma _ _ r) = r x
|
|
in VPair c1 c2
|
|
|
|
go VPath{} phi p p0 =
|
|
let
|
|
~(VPath ai1 u1 v1) = fam VI1
|
|
~(VPath ai0 u0 v0) = fam VI0
|
|
getA (VPath a _ _) = a
|
|
u' x = let ~(VPath _ u _) = fam x in u
|
|
v' x = let ~(VPath _ _ v) = fam x in v
|
|
in
|
|
VLine (ai1 @@ VI1) u1 v1 \j ->
|
|
let
|
|
jc = reduceCube' env j
|
|
in comp env (VLam ivar VI (getA . fam))
|
|
(orFormula [phi, jc, notFormula jc])
|
|
(VLam "j" VI \v ->
|
|
let
|
|
VSystem (FMap sys) = p @@ v
|
|
sys' = fmap (flip (pathp env ai0 u0 v0) j) sys
|
|
in mkVSystem $ Map.fromList [ (phi, mapVSystem (p @@ v) (flip (pathp env ai0 u0 v0) j))
|
|
, (notFormula jc, u' v)
|
|
, (jc, v' v)
|
|
])
|
|
(pathp env (ai0 @@ VI0) u0 v0 p0 j)
|
|
|
|
go VGlue{} psi b b0 =
|
|
let
|
|
base i = let VGlue base _ _ _ = force $ fam i in base
|
|
phi i =
|
|
case force (fam i) of
|
|
VGlue _ phi _ _ -> fromJust (reduceCube env phi)
|
|
x -> error (show x)
|
|
types i = let VGlue _ _ types _ = force $ fam i in types
|
|
equivs i = let VGlue _ _ _ equivs = force $ fam i in equivs
|
|
|
|
a i = mapVSystem (b @@ i) (unglue (base i) (phi i) (types i) (equivs i))
|
|
a0 = unglue (base VI0) (phi VI0) (types VI0) (equivs VI0) b0
|
|
|
|
del = faceForall phi
|
|
a1' = comp env (VLam "i" VI base) psi (VLam "i" VI a) a0
|
|
t1' = comp env (VLam "i" VI types) psi (VLam "i" VI (b @@)) b0
|
|
omega = pres env types base (flip mapVSystem proj1 . equivs) psi b b0
|
|
t1alpha = opEquiv env (base VI1) (types VI1) (equivs VI1) (orFormula [del, psi]) ts ps a1'
|
|
(t1, alpha) = (proj1 t1alpha, proj2 t1alpha)
|
|
|
|
ts = VSystem (FMap (Map.fromList [(del, t1'), (psi, b @@ VI1)]))
|
|
ps = VSystem (FMap (Map.fromList [(del, omega), (psi, VLine (VLam "j" VI \_ -> base VI1) a1' a1' (\j -> a1'))]))
|
|
|
|
a1 = comp env (VLam "j" VI (const (base VI1))) (orFormula [phi VI1, psi]) (VLam "j" VI \j -> a1_sys j) a1'
|
|
a1_sys j = VSystem (FMap (Map.fromList [(phi VI1, pathp env (base VI1) a1' (mapVSystem (equivs VI1) proj1) alpha j), (psi, a VI1)]))
|
|
b1 = introGlue (base VI1) (phi VI1) (types VI1) (equivs VI1) t1 a1
|
|
in b1
|
|
|
|
go VBool{} _ _ a0 = a0
|
|
go a P.Top u a0 = u @@ VI1
|
|
go a phi u a0 = stuck
|
|
|
|
comp env va phi u a0 =
|
|
if phi == P.Top
|
|
then VEqGlued (VComp va phi' u a0) (u @@ VI1)
|
|
else VComp va phi' u a0
|
|
where
|
|
phi' = toValue phi
|
|
|
|
opEquiv :: Env -> Value -> Value -> Value -> Formula -> Value -> Value -> Value -> Value
|
|
opEquiv env aT tT f phi t p a = VOfSub ty (toValue phi) (VPair t p) v where
|
|
fun = proj1 f
|
|
ty = VSigma "x" tT \x -> VPath (VLam "i" VI (const aT)) a (fun @@ x)
|
|
sys = Map.singleton phi (VPair t p)
|
|
v = contr env ty (proj2 f @@ a) phi (VSystem (FMap sys))
|
|
|
|
force :: Value -> Value
|
|
force (VEqGlued x _) = force x
|
|
force (VOfSub _ _ _ x) = force x
|
|
force x = x
|
|
|
|
faceForall :: (Value -> Formula) -> Formula
|
|
faceForall k = go (k (VVar "$elim")) where
|
|
go (P.Is0 "$elim") = P.Bot
|
|
go (P.Is1 "$elim") = P.Bot
|
|
go (P.Or a b) = orFormula [go a, go b]
|
|
go (P.And a b) = andFormula [go a, go b]
|
|
go x = x
|
|
|
|
pres :: Env -> (Value -> Value) -> (Value -> Value) -> (Value -> Value) -> Formula -> Value -> Value -> Value
|
|
pres env tT tA f phi t t0 = VOfSub (VPath (tA VI1) c1 c2) (toValue phi) base (VLine (tA VI1) c1 c2 cont) where
|
|
c1 = comp env (VLam "i" VI tA) phi (VLam "i" VI \j -> mapVSystem t (f j @@)) (f VI0 @@ t0)
|
|
c2 = f VI1 @@ comp env (VLam "i" VI tA) phi t t0
|
|
base = VLine (tA VI1) (f VI1 @@ (t @@ VI1)) (f VI1 @@ (t @@ VI1)) (\i -> f VI1 @@ (t @@ VI1))
|
|
cont j =
|
|
let v i = fill env i tT phi t t0
|
|
form = orFormula [phi, fromJust (reduceCube env j)]
|
|
a0 = f VI0 @@ t0
|
|
in comp env (VLam "I" VI tA) form
|
|
(VLam "I" VI (\j -> VSystem (FMap (Map.fromList [(form, f j @@ v j)]))))
|
|
a0
|
|
|
|
contr :: Env -> Value -> Value -> Formula -> Value -> Value
|
|
contr env a aC phi u =
|
|
comp env (VLam "i" VI (const a)) phi
|
|
(VLam "i" VI (pathp env a u (proj1 aC) (proj2 aC @@ u)))
|
|
(proj1 aC)
|
|
|
|
-- t : Partial phi T
|
|
-- T : Type
|
|
-- a : A
|
|
-- f : Equiv T A
|
|
|
|
mkVSystem :: Map.Map Formula Value -> Value
|
|
mkVSystem mp
|
|
| Just e <- Map.lookup P.Top mp = e
|
|
| otherwise = VSystem $ FMap $ Map.filterWithKey f mp
|
|
where
|
|
f P.Bot _ = False
|
|
f _ _ = True
|
|
|
|
reduceCube' :: Env -> Value -> Formula
|
|
reduceCube' env = fromJust . reduceCube env
|
|
|
|
mapVSystem :: Value -> (Value -> Value) -> Value
|
|
mapVSystem (VSystem ss) f = VSystem (mapSystem ss f)
|
|
mapVSystem x f = f x
|
|
|
|
evalSystem :: Env -> Map.Map Formula Term -> Value
|
|
evalSystem env face = mk . Map.fromList . mapMaybe (uncurry go) . Map.toList $ face where
|
|
go :: Formula -> Term -> Maybe (Formula, Value)
|
|
go face tm
|
|
| VI0 <- toValue' env face = Nothing
|
|
| otherwise = Just (evalF env face, eval env tm)
|
|
|
|
evalF env tm =
|
|
case toFormula (toValue' env tm) of
|
|
Just f -> f
|
|
Nothing -> error $ "eval turned formula into non formula"
|
|
|
|
mk x = case Map.toList x of
|
|
[(_, x)] -> x
|
|
_ -> mkVSystem x
|
|
|
|
glue :: Value -> Formula -> Value -> Value -> Value
|
|
-- glue baseT P.Top types _equivs = types
|
|
glue baseT phi types equivs = VGlue baseT (toValue phi) types equivs
|
|
|
|
introGlue :: Value -> Formula -> Value -> Value -> Value -> Value -> Value
|
|
introGlue baseT P.Top types equivs t a = t
|
|
introGlue baseT phi types equivs t a = VGlueIntro baseT (toValue phi) types equivs t a
|
|
|
|
unglue :: Value -> Formula -> Value -> Value -> Value -> Value
|
|
unglue baseT P.Top types equivs b = mapVSystem equivs ((@@ b) . proj1)
|
|
unglue baseT phi types equivs val =
|
|
VOfSub baseT (toValue phi) (mapVSystem equivs ((@@ val) . proj1)) (VGlueElim baseT (toValue phi) types equivs val)
|
|
|
|
eval :: Env -> Term -> Value
|
|
eval env = \case
|
|
Var v ->
|
|
case Map.lookup v (names env) of
|
|
Just (_, vl) -> vl
|
|
Nothing -> error $ "variable not in scope: " ++ show v
|
|
|
|
App f x -> eval env f @@ eval env x
|
|
|
|
Lam s d b ->
|
|
let d' = eval env d
|
|
in VLam s d' \a -> eval env{ names = Map.insert s (d', a) (names env) } b
|
|
|
|
Let s t b d ->
|
|
let b' = eval env b
|
|
t' = eval env t
|
|
in eval env{ names = Map.insert s (t', b') (names env) } d
|
|
|
|
Pi s d r ->
|
|
let d' = eval env d
|
|
in VPi s d' \a -> eval env{ names = Map.insert s (d', a) (names env) } r
|
|
|
|
Sigma s d r ->
|
|
let d' = eval env d
|
|
in VSigma s d' \a -> eval env{ names = Map.insert s (d', a) (names env) } r
|
|
|
|
Pair a b -> VPair (eval env a) (eval env b)
|
|
Proj1 x -> proj1 (eval env x)
|
|
Proj2 y -> proj2 (eval env y)
|
|
|
|
Type -> VType
|
|
Typeω -> VTypeω
|
|
|
|
I -> VI
|
|
I0 -> VI0
|
|
I1 -> VI1
|
|
|
|
Path p x y -> VPath (eval env p) (eval env x) (eval env y)
|
|
Partial r a -> VPartial (eval env r) (eval env a)
|
|
PartialP r a -> VPartialP (eval env r) (eval env a)
|
|
|
|
PathI p x y s e -> VLine (eval env p) (eval env x) (eval env y) (\ a -> eval env{ names = Map.insert s (VI, a) (names env) } e)
|
|
PathP p x y f i -> pathp env (eval env p) (eval env x) (eval env y) (eval env f) (eval env i)
|
|
|
|
Sub p x y -> VSub (eval env p) (eval env x) (eval env y)
|
|
InclSub a phi u a0 -> VOfSub (eval env a) (eval env phi) (eval env u) (eval env a0)
|
|
|
|
IAnd x y -> iand (eval env x) (eval env y)
|
|
IOr x y -> ior (eval env x) (eval env y)
|
|
INot x -> inot (eval env x)
|
|
|
|
Comp a phi u a0 ->
|
|
case reduceCube env (eval env phi) of
|
|
Just formula -> comp env (eval env a) formula (eval env u) (eval env a0)
|
|
Nothing -> VComp (eval env a) (eval env phi) (eval env u) (eval env a0)
|
|
|
|
System fs -> evalSystem env (getSystem fs)
|
|
|
|
GlueTy a phi types equivs ->
|
|
let phi' = eval env phi in
|
|
case reduceCube env phi' of
|
|
Just formula -> glue (eval env a) formula (eval env types) (eval env equivs)
|
|
Nothing -> VGlue (eval env a) phi' (eval env types) (eval env equivs)
|
|
|
|
Glue a phi types equivs t a0 ->
|
|
let phi' = eval env phi
|
|
t' = eval env t
|
|
a0' = eval env a0
|
|
types' = eval env types
|
|
equivs' = eval env equivs
|
|
a' = eval env a
|
|
in
|
|
case reduceCube env phi' of
|
|
Just formula -> introGlue a' formula types' equivs' t' a0'
|
|
Nothing -> VGlueIntro a' phi' types' equivs' t' a0'
|
|
|
|
Unglue a phi types equivs val ->
|
|
let phi' = eval env phi
|
|
val' = eval env val
|
|
types' = eval env types
|
|
equivs' = eval env equivs
|
|
a' = eval env a
|
|
in
|
|
case reduceCube env phi' of
|
|
Just formula -> unglue a' formula types' equivs' val'
|
|
Nothing -> VGlueElim a' phi' types' equivs' val'
|
|
|
|
If p x y t -> elimBool (eval env p) (eval env x) (eval env y) (eval env t)
|
|
Tt -> VTrue
|
|
Ff -> VFalse
|
|
Bool -> VBool
|
|
|
|
elimBool :: Value -> Value -> Value -> Value -> Value
|
|
elimBool _ x _ (VEqGlued _ VTrue) = x
|
|
elimBool _ x _ (VOfSub _ _ _ VTrue) = x
|
|
elimBool _ x _ VTrue = x
|
|
|
|
elimBool _ _ y (VEqGlued _ VFalse) = y
|
|
elimBool _ _ y (VOfSub _ _ _ VFalse) = y
|
|
elimBool _ _ y VFalse = y
|
|
|
|
elimBool p x y t = VIf p x y t
|
|
|
|
data UnifyError
|
|
= Mismatch Value Value
|
|
| NotPiType Value
|
|
| NotPartialType Formula Value
|
|
| NotSigmaType Value
|
|
| NotSort Value
|
|
deriving (Show, Typeable, Exception)
|
|
|
|
unify :: HasCallStack => Env -> Value -> Value -> IO ()
|
|
unify env (VEqGlued a b) c =
|
|
unify env a c `catch` \e -> const (unify env b c) (e :: UnifyError)
|
|
unify env c (VEqGlued a b) =
|
|
unify env c a `catch` \e -> const (unify env c b) (e :: UnifyError)
|
|
|
|
unify env (VLine a x y f) e =
|
|
let env' = env { names = Map.insert "i" (VI, VVar "i") (names env) }
|
|
in unify env' (f (VVar "i")) (pathp env' a x y e (VVar "i"))
|
|
unify env e (VLine a x y f) =
|
|
let env' = env { names = Map.insert "i" (VI, VVar "i") (names env) }
|
|
in unify env' (f (VVar "i")) (pathp env' a x y e (VVar "i"))
|
|
|
|
unify env (VPartial r b) (VPartial r' b') = do
|
|
unify env b b'
|
|
case sameCube env r r' of
|
|
Just True -> pure ()
|
|
_ -> unify env r r'
|
|
|
|
unify env (VPartial r b) x = do
|
|
case sameCube env r VI1 of
|
|
Just True -> pure ()
|
|
_ -> unify env r VI1
|
|
unify env b x
|
|
|
|
unify env x (VPartial r b) = do
|
|
case sameCube env r VI1 of
|
|
Just True -> pure ()
|
|
_ -> unify env r VI1
|
|
unify env x b
|
|
|
|
unify env (VSub a phi _u0) vl = unify env a vl
|
|
|
|
unify env u1 (VOfSub _a phi u0 a) = do
|
|
case sameCube env phi VI1 of
|
|
Just True -> unify env u1 u0
|
|
_ -> unify env u1 a
|
|
|
|
unify env (VOfSub _a phi u0 a) u1 = do
|
|
case sameCube env phi VI1 of
|
|
Just True -> unify env u1 u0
|
|
_ -> unify env u1 a
|
|
|
|
unify env vl1@(VNe x sp) vl2@(VNe y sp')
|
|
| x == y = traverse_ (uncurry unifySp) (zip sp sp')
|
|
| otherwise = throwIO $ Mismatch vl1 vl2
|
|
where
|
|
unifySp (PApp x) (PApp y) = unify env x y
|
|
unifySp (PPathP _a _x _y i) (PPathP _a' _x' _y' i') = unify env i i'
|
|
unifySp PProj1 PProj1 = pure ()
|
|
unifySp PProj2 PProj2 = pure ()
|
|
unifySp _ _ = throwIO $ Mismatch vl1 vl2
|
|
|
|
unify env (VLam x _ k) e = unify env (k (VVar x)) (e @@ VVar x)
|
|
unify env e (VLam x _ k) = unify env (e @@ VVar x) (k (VVar x))
|
|
|
|
unify env (VPi x d r) (VPi _ d' r') = do
|
|
unify env d d'
|
|
unify env (r (VVar x)) (r' (VVar x))
|
|
|
|
unify env (VSigma x d r) (VSigma _ d' r') = do
|
|
unify env d d'
|
|
unify env (r (VVar x)) (r' (VVar x))
|
|
|
|
unify env VType VType = pure ()
|
|
unify env VI VI = pure ()
|
|
unify env VBool VBool = pure ()
|
|
|
|
unify env (VPair a b) e = unify env a (proj1 e) *> unify env b (proj2 e)
|
|
unify env e (VPair a b) = unify env a (proj1 e) *> unify env b (proj2 e)
|
|
|
|
unify env (VPath a x y) (VPath a' x' y') = unify env a a' *> unify env x x' *> unify env y y'
|
|
unify env (VComp a phi u a0) (VComp a' phi' u' a0') =
|
|
traverse_ (uncurry (unify env))
|
|
[ (a, a')
|
|
, (phi, phi')
|
|
, (u, u')
|
|
, (a0, a0')
|
|
]
|
|
|
|
unify env (VComp a (reduceCube env -> Just P.Top) u a0) vl =
|
|
unify env (u @@ VI1) vl
|
|
|
|
unify env vl (VComp a (reduceCube env -> Just P.Top) u a0) =
|
|
unify env (u @@ VI1) vl
|
|
|
|
unify env (VSystem fs) vl
|
|
| ((_, vl'):_) <-
|
|
Map.toList (Map.filterWithKey (\f _ -> isTrue (toValue' env f)) (getSystem fs))
|
|
= unify env vl' vl
|
|
| Map.null (getSystem fs) = pure ()
|
|
|
|
unify env vl (VSystem fs)
|
|
| ((_, vl'):_) <-
|
|
Map.toList (Map.filterWithKey (\f _ -> isTrue (toValue' env f)) (getSystem fs))
|
|
= unify env vl' vl
|
|
| Map.null (getSystem fs) = pure ()
|
|
|
|
unify env VType VTypeω = pure ()
|
|
unify env VTypeω VTypeω = pure ()
|
|
|
|
unify env (VGlue _ VI1 b _) x = unify env b x
|
|
|
|
unify env VTrue VTrue = pure ()
|
|
unify env VFalse VFalse = pure ()
|
|
unify env (VIf p a b c) (VIf p' a' b' c') = traverse_ (uncurry (unify env)) [(p, p'), (a, a'), (b, b'), (c, c')]
|
|
|
|
unify env x y =
|
|
case sameCube env x y of
|
|
Just True -> pure ()
|
|
_ -> throwIO $ Mismatch x y
|
|
|
|
reduceCube :: Env -> Value -> Maybe Formula
|
|
reduceCube env x = fmap (toDNF . simplify) (toFormula x) where
|
|
simplify :: Formula -> Formula
|
|
simplify (P.Is0 x) =
|
|
case Map.lookup x (names env) of
|
|
Just (VI, VI0) -> P.Top
|
|
Just (VI, VI1) -> P.Bot
|
|
_ -> P.Is0 x
|
|
simplify (P.Is1 x) =
|
|
case Map.lookup x (names env) of
|
|
Just (VI, VI1) -> P.Top
|
|
Just (VI, VI0) -> P.Bot
|
|
_ -> P.Is1 x
|
|
simplify (P.And x y) = P.And (simplify x) (simplify y)
|
|
simplify (P.Or x y) = P.Or (simplify x) (simplify y)
|
|
simplify x = x
|
|
|
|
sameCube :: Env -> Value -> Value -> Maybe Bool
|
|
sameCube env x y =
|
|
case (reduceCube env x, reduceCube env y) of
|
|
(Just x, Just y) -> Just (x == y)
|
|
_ -> Nothing
|
|
|
|
toFormula :: Value -> Maybe Formula
|
|
toFormula VI0 = Just P.Bot
|
|
toFormula VI1 = Just P.Top
|
|
toFormula (VNe x []) = Just (P.Is1 x)
|
|
toFormula (VINot f) = notFormula <$> toFormula f
|
|
toFormula (VIAnd x y) = do
|
|
s <- toFormula y
|
|
t <- toFormula x
|
|
pure $ andFormula [s, t]
|
|
toFormula (VIOr x y) = do
|
|
s <- toFormula y
|
|
t <- toFormula x
|
|
pure $ orFormula [s, t]
|
|
toFormula _ = Nothing
|
|
|
|
faceInEnv :: Env -> Face -> Bool
|
|
faceInEnv e f = Map.isSubmapOf (getFace f) (faceOfEnv (names e)) where
|
|
faceOfEnv = Map.map (\(_, v) -> case v of { VI1 -> True; VEqGlued _ VI1 -> True; _ -> False }) . Map.filter (\(_, v) -> isI v)
|
|
|
|
isI VI1 = True
|
|
isI VI0 = True
|
|
isI (VEqGlued _ x) = isI x
|
|
isI _ = False
|
|
|
|
isPiType :: Value -> IO (String, Value, Value -> Value)
|
|
isPiType (VPi x d r) = pure (x, d, r)
|
|
isPiType x = throwIO $ NotPiType x
|
|
|
|
isSigmaType :: Value -> IO (String, Value, Value -> Value)
|
|
isSigmaType (VSigma x d r) = pure (x, d, r)
|
|
isSigmaType x = throwIO $ NotSigmaType x
|
|
|
|
isPiOrPathType :: Value -> IO (Either (String, Value, Value -> Value) (Value, Value, Value))
|
|
isPiOrPathType (VPi x d r) = pure (Left (x, d, r))
|
|
isPiOrPathType (VPath x d r) = pure (Right (x, d, r))
|
|
isPiOrPathType x = throwIO $ NotPiType x
|
|
|
|
isPartialType :: Formula -> Value -> IO (Formula, Value)
|
|
isPartialType f p@(VPartial x y) =
|
|
case toFormula x of
|
|
Just x -> pure (x, y)
|
|
Nothing -> throwIO $ NotPartialType f p
|
|
isPartialType f p@(VPartialP x y) =
|
|
case toFormula x of
|
|
Just x -> pure (x, y)
|
|
Nothing -> throwIO $ NotPartialType f p
|
|
isPartialType f x = throwIO $ NotPartialType f x
|
|
|
|
getVar :: IO Value
|
|
getVar =
|
|
do
|
|
n <- atomicModifyIORef ref \x -> (x + 1, x)
|
|
pure (VVar (show n))
|
|
where
|
|
ref :: IORef Int
|
|
ref = unsafePerformIO (newIORef 0)
|
|
{-# NOINLINE ref #-}
|
|
|
|
fill :: Env
|
|
-> Value
|
|
-> (Value -> Value) -- (Γ i : I, A : Type)
|
|
-> Formula -- (phi : I)
|
|
-> Value -- (u : (i : I) -> Partial phi (A i))
|
|
-> Value -- (Sub (A i0) phi (u i0))
|
|
-> Value -- -> A i
|
|
fill env i a phi u a0 =
|
|
comp env
|
|
(VLam "j" VI \j -> a (i `iand` j))
|
|
(phi `P.Or` notFormula ifc)
|
|
(VLam "j" VI \j ->
|
|
mkVSystem (Map.fromList [ (phi, uiand j)
|
|
, (notFormula ifc, a0) ]))
|
|
a0
|
|
where
|
|
uiand j = u @@ (i `iand` j)
|
|
ifc = fromMaybe P.Bot $ (reduceCube env i)
|
|
|
|
toValue :: Formula -> Value
|
|
toValue P.Top = VI1
|
|
toValue P.Bot = VI0
|
|
toValue (P.And x y) = toValue x `iand` toValue y
|
|
toValue (P.Or x y) = toValue x `ior` toValue y
|
|
toValue (P.Is0 x) = inot (VVar x)
|
|
toValue (P.Is1 x) = VVar x
|
|
|
|
toValue' :: HasCallStack => Env -> Formula -> Value
|
|
toValue' env P.Top = VI1
|
|
toValue' env P.Bot = VI0
|
|
toValue' env (P.And x y) = toValue x `iand` toValue y
|
|
toValue' env (P.Or x y) = toValue x `ior` toValue y
|
|
toValue' env (P.Is0 x) =
|
|
case Map.lookup x (names env) of
|
|
Just (VI, VI0) -> VI1
|
|
Just (VI, VI1) -> VI0
|
|
Just (VI, x) -> inot x
|
|
vl -> error $ "type error in toValue' " ++ x ++ ": " ++ show vl
|
|
toValue' env (P.Is1 x) =
|
|
case Map.lookup x (names env) of
|
|
Just (VI, x) -> x
|
|
vl -> error $ "type error in toValue': Is1 " ++ show x ++ ": " ++ show vl
|
|
|
|
isTrue :: Value -> Bool
|
|
isTrue VI1 = True
|
|
isTrue _ = False
|
|
|
|
equiv :: Value -> Value -> Value
|
|
equiv t a = VSigma "f" (VPi "_" t (const a)) \f -> isEquiv t a f
|
|
|
|
isEquiv :: Value -> Value -> Value -> Value
|
|
isEquiv t a f = VPi "y" a \y -> isContr (VSigma "x" t \x -> VPath (VLam "_" VI (const a)) y (f @@ x))
|
|
|
|
isContr :: Value -> Value
|
|
isContr t = VSigma "x" t \x -> VPi "y" t \y -> VPath (VLam "_" VI (const t)) x y
|