Prototype, extremely bad code implementation of CCHM Cubical Type Theory
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

456 lines
14 KiB

3 years ago
  1. {-# LANGUAGE ViewPatterns #-}
  2. {-# LANGUAGE DeriveAnyClass #-}
  3. {-# LANGUAGE BlockArguments #-}
  4. {-# LANGUAGE LambdaCase #-}
  5. module Eval where
  6. import Syntax
  7. import qualified Data.Map.Strict as Map
  8. import Data.Foldable
  9. import Control.Exception
  10. import Data.Typeable
  11. import System.IO.Unsafe (unsafePerformIO)
  12. import Data.IORef
  13. import Systems
  14. import Presyntax (Formula)
  15. import qualified Presyntax as P
  16. import Data.Maybe
  17. import Debug.Trace
  18. import GHC.Stack
  19. iand :: Value -> Value -> Value
  20. iand = \case
  21. VI1 -> id
  22. VI0 -> const VI0
  23. x -> \case
  24. VI0 -> VI0
  25. VI1 -> x
  26. y -> VIAnd x y
  27. ior :: Value -> Value -> Value
  28. ior = \case
  29. VI0 -> id
  30. VI1 -> const VI1
  31. x -> \case
  32. VI1 -> VI1
  33. VI0 -> x
  34. y -> VIOr x y
  35. inot :: Value -> Value
  36. inot VI1 = VI0
  37. inot VI0 = VI1
  38. inot (VIOr x y) = iand (inot x) (inot y)
  39. inot (VIAnd x y) = ior (inot x) (inot y)
  40. inot (VINot x) = x
  41. inot x = VINot x
  42. (@@) :: Value -> Value -> Value
  43. VNe hd xs @@ vl = VNe hd (PApp vl:xs)
  44. VLam _ _ k @@ vl = k vl
  45. VEqGlued a b @@ vl = VEqGlued (a @@ vl) (b @@ vl)
  46. VOfSub a phi u0 x @@ vl = x @@ vl
  47. f @@ _ = error $ "can't apply argument to " ++ show f
  48. proj1 :: Value -> Value
  49. proj1 (VPair x _) = x
  50. proj1 (VEqGlued x y) = VEqGlued (proj1 x) (proj1 y)
  51. proj1 (VNe s xs) = VNe s (PProj1:xs)
  52. proj1 (VOfSub (VSigma _ d _) phi u0 x) = VOfSub d phi (proj1 u0) (proj1 x)
  53. proj1 x = error $ "can't proj1 " ++ show x
  54. proj2 :: Value -> Value
  55. proj2 (VPair _ y) = y
  56. proj2 (VEqGlued x y) = VEqGlued (proj1 x) (proj1 y)
  57. proj2 (VNe s xs) = VNe s (PProj2:xs)
  58. proj2 (VOfSub (VSigma _ d r) phi u0 x) =
  59. VOfSub (r (proj1 x)) phi (proj2 u0) (proj2 x)
  60. proj2 x = error $ "can't proj2 " ++ show x
  61. pathp :: Env -> Value -> Value -> Value -> Value -> Value -> Value
  62. pathp env p x y f@(VLine _a _x _y e) i =
  63. case reduceCube env i of
  64. Just P.Bot -> VEqGlued (e i) x
  65. Just P.Top -> VEqGlued (e i) y
  66. _ -> e i
  67. pathp env p x y (VEqGlued e e') i = VEqGlued (pathp env p x y e i) (pathp env p x y e' i)
  68. pathp env p x y (VNe hd sp) i =
  69. case reduceCube env i of
  70. Just P.Bot -> VEqGlued (VNe hd (PPathP p x y i:sp)) x
  71. Just P.Top -> VEqGlued (VNe hd (PPathP p x y i:sp)) y
  72. _ -> VNe hd (PPathP p x y i:sp)
  73. pathp env p x y (VOfSub _ _ _ v) i = pathp env p x y v i
  74. comp :: Env -> Value -> Formula -> Value -> Value -> Value
  75. comp env a@(VLam ivar VI fam) phi u a0 = go (fam undefined) phi u a0 where
  76. i = VVar ivar
  77. stuck :: Value
  78. stuck = maybeAddEq $ VComp a (toValue phi) u a0
  79. maybeAddEq :: Value -> Value
  80. maybeAddEq =
  81. if phi == P.Top
  82. then flip VEqGlued (u @@ VI1)
  83. else id
  84. go :: HasCallStack => Value -> Formula -> Value -> Value -> Value
  85. go VPi{} phi u a0 =
  86. let
  87. dom x = let VPi _ d _ = fam x in d
  88. rng x = let VPi _ d _ = fam x in d
  89. ai1 = dom VI0
  90. y' i y = fill env i (dom . inot . fam) P.Bot (VSystem emptySystem) y
  91. ybar i y = y' (inot i) y
  92. in VLam "x" ai1 \arg ->
  93. comp env
  94. (VLam ivar VI (\i -> rng (ybar i arg)))
  95. phi
  96. (VLam "i" VI \i -> mapVSystem (u @@ i) (@@ ybar i arg))
  97. (a0 @@ ybar VI0 arg)
  98. go VSigma{} phi u a0 =
  99. let
  100. dom x = let VSigma _ d _ = fam x in d
  101. rng x = let VSigma _ d _ = fam x in d
  102. a i = fill env i (dom . fam) phi (VLam "j" VI \v -> mapVSystem (u @@ v) proj1) (proj1 a0)
  103. c1 = comp env (VLam ivar VI (getd . fam)) phi (VLam "i" VI \v -> mapVSystem (u @@ v) proj1) (proj1 a0)
  104. c2 = comp env (VLam ivar VI (apr (a VI1) . fam)) phi (VLam "i" VI \v -> mapVSystem (u @@ v) proj2) (proj2 a0)
  105. getd (VSigma _ d _) = d
  106. apr x (VSigma _ _ r) = r x
  107. in VPair c1 c2
  108. go VPath{} phi p p0 =
  109. let
  110. ~(VPath ai1 u1 v1) = fam VI1
  111. ~(VPath ai0 u0 v0) = fam VI0
  112. getA (VPath a _ _) = a
  113. u' x = let ~(VPath _ u _) = fam x in u
  114. v' x = let ~(VPath _ _ v) = fam x in v
  115. in
  116. VLine (ai1 @@ VI1) u1 v1 \j ->
  117. let
  118. jc = reduceCube' env j
  119. in comp env (VLam ivar VI (getA . fam))
  120. (orFormula [phi, jc, notFormula jc])
  121. (VLam "j" VI \v ->
  122. let
  123. VSystem (FMap sys) = p @@ v
  124. sys' = fmap (flip (pathp env ai0 u0 v0) j) sys
  125. in mkVSystem $ Map.fromList [(phi, mapVSystem (p @@ v) (flip (pathp env ai0 u0 v0) j))
  126. , (notFormula jc, u' v), (jc, v' v)])
  127. (pathp env (ai0 @@ VI0) u0 v0 p0 j)
  128. go a P.Top u a0 = u @@ VI1
  129. go a phi u a0 = maybeAddEq stuck
  130. comp env va phi u a0 =
  131. if phi == P.Top
  132. then VEqGlued (VComp va phi' u a0) (u @@ VI1)
  133. else VComp va phi' u a0
  134. where
  135. phi' = toValue phi
  136. mkVSystem :: Map.Map Formula Value -> Value
  137. mkVSystem mp
  138. | Just e <- Map.lookup P.Top mp = e
  139. | otherwise = VSystem $ FMap $ Map.filterWithKey f mp
  140. where
  141. f P.Bot _ = False
  142. f _ _ = True
  143. reduceCube' :: Env -> Value -> Formula
  144. reduceCube' env = fromJust . reduceCube env
  145. mapVSystem :: Value -> (Value -> Value) -> Value
  146. mapVSystem (VSystem ss) f = VSystem (mapSystem ss f)
  147. mapVSystem x f = f x
  148. evalSystem :: Env -> Map.Map Formula Term -> Value
  149. evalSystem env face = mk . Map.mapMaybeWithKey go $ face where
  150. go :: Formula -> Term -> Maybe Value
  151. go face tm
  152. | VI0 <- toValue' env face = Nothing
  153. | otherwise = Just (eval env tm)
  154. differsFromEnv :: String -> Bool -> Bool
  155. differsFromEnv x True =
  156. case Map.lookup x (names env) of
  157. Just (VI, VI0) -> True
  158. _ -> False
  159. differsFromEnv x False =
  160. case Map.lookup x (names env) of
  161. Just (VI, VI1) -> True
  162. _ -> False
  163. mk x = case Map.toList x of
  164. [(_, x)] -> x
  165. _ -> mkVSystem x
  166. eval :: Env -> Term -> Value
  167. eval env = \case
  168. Var v ->
  169. case Map.lookup v (names env) of
  170. Just (_, vl) -> vl
  171. Nothing -> error $ "variable not in scope: " ++ show v
  172. App f x -> eval env f @@ eval env x
  173. Lam s d b ->
  174. let d' = eval env d
  175. in VLam s d' \a -> eval env{ names = Map.insert s (d', a) (names env) } b
  176. Let s t b d ->
  177. let b' = eval env b
  178. t' = eval env t
  179. in eval env{ names = Map.insert s (t', b') (names env) } d
  180. Pi s d r ->
  181. let d' = eval env d
  182. in VPi s d' \a -> eval env{ names = Map.insert s (d', a) (names env) } r
  183. Sigma s d r ->
  184. let d' = eval env d
  185. in VSigma s d' \a -> eval env{ names = Map.insert s (d', a) (names env) } r
  186. Pair a b -> VPair (eval env a) (eval env b)
  187. Proj1 x -> proj1 (eval env x)
  188. Proj2 y -> proj2 (eval env y)
  189. Type -> VType
  190. I -> VI
  191. I0 -> VI0
  192. I1 -> VI1
  193. Path p x y -> VPath (eval env p) (eval env x) (eval env y)
  194. Partial r a -> VPartial (eval env r) (eval env a)
  195. 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)
  196. PathP p x y f i -> pathp env (eval env p) (eval env x) (eval env y) (eval env f) (eval env i)
  197. Sub p x y -> VSub (eval env p) (eval env x) (eval env y)
  198. InclSub a phi u a0 -> VOfSub (eval env a) (eval env phi) (eval env u) (eval env a0)
  199. IAnd x y -> iand (eval env x) (eval env y)
  200. IOr x y -> ior (eval env x) (eval env y)
  201. INot x -> inot (eval env x)
  202. Comp a phi u a0 ->
  203. case reduceCube env (eval env phi) of
  204. Just formula -> comp env (eval env a) formula (eval env u) (eval env a0)
  205. Nothing -> VComp (eval env a) (eval env phi) (eval env u) (eval env a0)
  206. System fs -> evalSystem env (getSystem fs)
  207. data UnifyError
  208. = Mismatch Value Value
  209. | NotPiType Value
  210. | NotPartialType Formula Value
  211. | NotSigmaType Value
  212. deriving (Show, Typeable, Exception)
  213. unify :: Env -> Value -> Value -> IO ()
  214. unify env (VEqGlued a b) c =
  215. unify env a c `catch` \e -> const (unify env b c) (e :: UnifyError)
  216. unify env c (VEqGlued a b) =
  217. unify env c a `catch` \e -> const (unify env c b) (e :: UnifyError)
  218. unify env (VLine a x y f) e = unify env (f (VVar "i")) (pathp env a x y e (VVar "i"))
  219. unify env e (VLine a x y f) = unify env (f (VVar "i")) (pathp env a x y e (VVar "i"))
  220. unify env (VPartial r b) (VPartial r' b') = do
  221. unify env b b'
  222. case sameCube env r r' of
  223. Just True -> pure ()
  224. _ -> unify env r r'
  225. unify env (VPartial r b) x = do
  226. case sameCube env r VI1 of
  227. Just True -> pure ()
  228. _ -> unify env r VI1
  229. unify env b x
  230. unify env x (VPartial r b) = do
  231. case sameCube env r VI1 of
  232. Just True -> pure ()
  233. _ -> unify env r VI1
  234. unify env x b
  235. unify env (VSub a phi _u0) vl = unify env a vl
  236. unify env u1 (VOfSub _a phi u0 a) = do
  237. case sameCube env phi VI1 of
  238. Just True -> unify env u1 u0
  239. _ -> unify env u1 a
  240. unify env (VOfSub _a phi u0 a) u1 = do
  241. case sameCube env phi VI1 of
  242. Just True -> unify env u1 u0
  243. _ -> unify env u1 a
  244. unify env vl1@(VNe x sp) vl2@(VNe y sp')
  245. | x == y = traverse_ (uncurry unifySp) (zip sp sp')
  246. | otherwise = throwIO $ Mismatch vl1 vl2
  247. where
  248. unifySp (PApp x) (PApp y) = unify env x y
  249. unifySp (PPathP _a _x _y i) (PPathP _a' _x' _y' i') = unify env i i'
  250. unifySp PProj1 PProj1 = pure ()
  251. unifySp PProj2 PProj2 = pure ()
  252. unify env (VLam x _ k) e = unify env (k (VVar x)) (e @@ VVar x)
  253. unify env e (VLam x _ k) = unify env (e @@ VVar x) (k (VVar x))
  254. unify env (VPi x d r) (VPi _ d' r') = do
  255. unify env d d'
  256. unify env (r (VVar x)) (r' (VVar x))
  257. unify env (VSigma x d r) (VSigma _ d' r') = do
  258. unify env d d'
  259. unify env (r (VVar x)) (r' (VVar x))
  260. unify env VType VType = pure ()
  261. unify env VI VI = pure ()
  262. unify env (VPair a b) (VPair c d) = unify env a c *> unify env b d
  263. unify env (VPath a x y) (VPath a' x' y') = unify env a a' *> unify env x x' *> unify env y y'
  264. unify env (VSystem fs) vl
  265. | ((_, vl'):_) <- Map.toList (Map.filterWithKey (\f _ -> isTrue (toValue' env f)) (getSystem fs))
  266. = unify env vl' vl
  267. unify env vl (VSystem fs)
  268. | ((_, vl'):_) <- Map.toList (Map.filterWithKey (\f _ -> isTrue (toValue' env f)) (getSystem fs))
  269. = unify env vl' vl
  270. unify env x y =
  271. case sameCube env x y of
  272. Just True -> pure ()
  273. _ -> throwIO $ Mismatch x y
  274. reduceCube :: Env -> Value -> Maybe Formula
  275. reduceCube env x = fmap (toDNF . simplify) (toFormula x) where
  276. simplify :: Formula -> Formula
  277. simplify (P.Is0 x) =
  278. case Map.lookup x (names env) of
  279. Just (VI, VI0) -> P.Top
  280. Just (VI, VI1) -> P.Bot
  281. _ -> P.Is0 x
  282. simplify (P.Is1 x) =
  283. case Map.lookup x (names env) of
  284. Just (VI, VI1) -> P.Top
  285. Just (VI, VI0) -> P.Bot
  286. _ -> P.Is0 x
  287. simplify (P.And x y) = P.And (simplify x) (simplify y)
  288. simplify (P.Or x y) = P.Or (simplify x) (simplify y)
  289. simplify x = x
  290. sameCube :: Env -> Value -> Value -> Maybe Bool
  291. sameCube env x y =
  292. case (reduceCube env x, reduceCube env y) of
  293. (Just x, Just y) -> Just (x == y)
  294. _ -> Nothing
  295. toFormula :: Value -> Maybe Formula
  296. toFormula VI0 = Just P.Bot
  297. toFormula VI1 = Just P.Top
  298. toFormula (VNe x []) = Just (P.Is1 x)
  299. toFormula (VINot f) = notFormula <$> toFormula f
  300. toFormula (VIAnd x y) = do
  301. s <- toFormula y
  302. t <- toFormula x
  303. pure $ andFormula [s, t]
  304. toFormula (VIOr x y) = do
  305. s <- toFormula y
  306. t <- toFormula x
  307. pure $ orFormula [s, t]
  308. toFormula _ = Nothing
  309. faceInEnv :: Env -> Face -> Bool
  310. faceInEnv e f = Map.isSubmapOf (getFace f) (faceOfEnv (names e)) where
  311. faceOfEnv = Map.map (\(_, v) -> case v of { VI1 -> True; VEqGlued _ VI1 -> True; _ -> False }) . Map.filter (\(_, v) -> isI v)
  312. isI VI1 = True
  313. isI VI0 = True
  314. isI (VEqGlued _ x) = isI x
  315. isI _ = False
  316. isPiType :: Value -> IO (String, Value, Value -> Value)
  317. isPiType (VPi x d r) = pure (x, d, r)
  318. isPiType x = throwIO $ NotPiType x
  319. isSigmaType :: Value -> IO (String, Value, Value -> Value)
  320. isSigmaType (VSigma x d r) = pure (x, d, r)
  321. isSigmaType x = throwIO $ NotSigmaType x
  322. isPiOrPathType :: Value -> IO (Either (String, Value, Value -> Value) (Value, Value, Value))
  323. isPiOrPathType (VPi x d r) = pure (Left (x, d, r))
  324. isPiOrPathType (VPath x d r) = pure (Right (x, d, r))
  325. isPiOrPathType x = throwIO $ NotPiType x
  326. isPartialType :: Formula -> Value -> IO (Formula, Value)
  327. isPartialType f p@(VPartial x y) =
  328. case toFormula x of
  329. Just x -> pure (x, y)
  330. Nothing -> throwIO $ NotPartialType f p
  331. isPartialType f x = throwIO $ NotPartialType f x
  332. getVar :: IO Value
  333. getVar =
  334. do
  335. n <- atomicModifyIORef ref \x -> (x + 1, x)
  336. pure (VVar (show n))
  337. where
  338. ref :: IORef Int
  339. ref = unsafePerformIO (newIORef 0)
  340. {-# NOINLINE ref #-}
  341. fill :: Env
  342. -> Value
  343. -> (Value -> Value) -- (Γ i : I, A : Type)
  344. -> Formula -- (phi : I)
  345. -> Value -- (u : (i : I) -> Partial phi (A i))
  346. -> Value -- (Sub (A i0) phi (u i0))
  347. -> Value -- -> A i
  348. fill env i a phi u a0 =
  349. comp env
  350. (VLam "j" VI \j -> a (i `iand` j))
  351. (phi `P.Or` ifc)
  352. (VLam "j" VI \j ->
  353. mkVSystem (Map.fromList [ (phi, uiand j)
  354. , (notFormula ifc, a0) ]))
  355. a0
  356. where
  357. uiand j = u @@ (i `iand` j)
  358. ifc = fromJust (reduceCube env i)
  359. toValue :: Formula -> Value
  360. toValue P.Top = VI1
  361. toValue P.Bot = VI0
  362. toValue (P.And x y) = toValue x `iand` toValue y
  363. toValue (P.Or x y) = toValue x `ior` toValue y
  364. toValue (P.Is0 x) = inot (VVar x)
  365. toValue (P.Is1 x) = VVar x
  366. toValue' :: Env -> Formula -> Value
  367. toValue' env P.Top = VI1
  368. toValue' env P.Bot = VI0
  369. toValue' env (P.And x y) = toValue x `iand` toValue y
  370. toValue' env (P.Or x y) = toValue x `ior` toValue y
  371. toValue' env (P.Is0 x) =
  372. case Map.lookup x (names env) of
  373. Just (VI, VI0) -> VI1
  374. Just (VI, VI1) -> VI0
  375. Just (VI, x) -> inot x
  376. _ -> error $ "type error in toValue'"
  377. toValue' env (P.Is1 x) =
  378. case Map.lookup x (names env) of
  379. Just (VI, x) -> x
  380. _ -> error $ "type error in toValue'"
  381. isTrue :: Value -> Bool
  382. isTrue VI1 = True
  383. isTrue _ = False