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.

390 lines
12 KiB

3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
  1. {-# LANGUAGE ViewPatterns #-}
  2. {-# LANGUAGE LambdaCase #-}
  3. {-# LANGUAGE BlockArguments #-}
  4. {-# LANGUAGE TupleSections #-}
  5. {-# LANGUAGE DeriveAnyClass #-}
  6. module Elab where
  7. import Control.Exception
  8. import Control.Monad
  9. import qualified Data.Map.Strict as Map
  10. import qualified Data.Set as Set
  11. import Data.Traversable
  12. import Data.Set (Set)
  13. import Data.Typeable
  14. import Data.Foldable
  15. import Eval
  16. import qualified Presyntax as P
  17. import Syntax
  18. import Systems
  19. data TypeError
  20. = NotInScope String
  21. | UnifyError UnifyError
  22. | WrongFaces Value [([Value], Value, Elab.TypeError)]
  23. | InSpan (Int, Int) (Int, Int) Elab.TypeError
  24. | IncompleteSystem P.Formula P.Formula
  25. | IncompatibleFaces (P.Formula, Term) (P.Formula, Term) Elab.TypeError
  26. | InvalidSystem (Set Face) (Set Face)
  27. deriving (Show, Typeable, Exception)
  28. check :: Env -> P.Exp -> Value -> IO Term
  29. check env (P.Span s e exp) wants =
  30. check env exp wants
  31. `catch` \case
  32. InSpan s e err -> throwIO $ InSpan s e err
  33. err -> throwIO $ InSpan s e err
  34. `catch` \er -> throwIO $ InSpan s e (UnifyError er)
  35. check env exp (VSub a fm@(toFormula -> Just phi) el) = do
  36. tm <- check env exp a
  37. for (addFormula phi env) \env -> do
  38. let tm' = eval env tm
  39. unifyTC env tm' el
  40. pure (InclSub (quote a) (quote fm) (quote el) tm)
  41. check env (P.Let v t d b) expected = do
  42. ty <- check env t VTypeω
  43. let ty' = eval env ty
  44. d <- check env d ty'
  45. let d' = eval env d
  46. b <- check env { names = Map.insert v (ty', d') (names env) } b expected
  47. pure (Let v (quote ty') d b)
  48. check env (P.Pair a b) expected = do
  49. (_, fst, snd) <- isSigmaType expected
  50. a <- check env a fst
  51. let a' = eval env a
  52. b <- check env b (snd a')
  53. pure (Pair a b)
  54. check env (P.Partial fs) ty = do
  55. let formula = orFormula (map fst fs)
  56. (extent, ty) <- isPartialType formula ty
  57. let ourFaces = Systems.faces formula
  58. extentFaces = Systems.faces extent
  59. unless (toDNF formula == toDNF extent) $
  60. throwIO $ IncompleteSystem formula extent
  61. let range = formulaToTm $ toDNF formula
  62. rangeTm <- check env range VI
  63. let rangeTy = eval env rangeTm
  64. ts <- for fs $ \(fn, tn) -> do
  65. tms <- for (addFormula fn env) \env -> check env tn ty
  66. pure (fn, head tms)
  67. fmap (System . FMap . Map.fromList) $ for ts \(fn, tn) -> do
  68. for ts \(fm, tm) -> do
  69. when (fn /= fm && possible (fn `P.And` fm)) do
  70. for_ (addFormula (fn `P.And` fm) env) $ \env ->
  71. unifyTC (env) (eval env tn) (eval env tm)
  72. `catch` \e -> throwIO (IncompatibleFaces (fn, tn) (fm, tm) e)
  73. pure (fn, tn)
  74. check env exp (VPartial fm@(toFormula -> Just phi) a) = do
  75. case addFormula phi env of
  76. [] -> pure $ System (FMap mempty)
  77. (x:xs) -> do
  78. tm <- check x exp a
  79. for_ xs $ \e -> check e exp a
  80. pure tm
  81. check env (P.Lam s b) expected = do
  82. expc <- isPiOrPathType expected
  83. case expc of
  84. Left (_, d, r) -> do -- function
  85. bd <- check env { names = Map.insert s (makeValueGluingSub d s) (names env) } b (r (VVar s))
  86. pure (Lam s (quote d) bd)
  87. Right (a, x, y) -> do
  88. bd <- check env { names = Map.insert s (VI, VVar s) (names env) } b (a @@ VVar s)
  89. let t = Lam s I bd
  90. t' = eval env t
  91. checkBoundary env [s] t'
  92. [ ([VI0], x)
  93. , ([VI1], y)
  94. ]
  95. pure (PathI (quote a) (quote x) (quote y) s bd)
  96. check env exp expected = do
  97. (term, actual) <- infer env exp
  98. unifyTC env actual expected
  99. pure term
  100. makeValueGluingSub :: Value -> String -> (Value, Value)
  101. makeValueGluingSub ty@(VSub a phi a0) s = (ty, VOfSub a phi a0 (VVar s))
  102. makeValueGluingSub ty s = (ty, VVar s)
  103. addFormula :: P.Formula -> Env -> [Env]
  104. addFormula (P.And x y) = addFormula x >=> addFormula y
  105. addFormula (P.Or x y) = (++) <$> addFormula x <*> addFormula y
  106. addFormula P.Top = pure
  107. addFormula P.Bot = const []
  108. addFormula (P.Is0 x) = \env -> pure env{ names = Map.insert x (VI, VI0) (names env) }
  109. addFormula (P.Is1 x) = \env -> pure env{ names = Map.insert x (VI, VI1) (names env) }
  110. unifyTC :: Env -> Value -> Value -> IO ()
  111. unifyTC env a b = unify env a b `catch` \e -> const (throwIO (UnifyError (Mismatch a b))) (e :: UnifyError)
  112. checkBoundary :: Env -> [String] -> Value -> [([Value], Value)] -> IO ()
  113. checkBoundary env ns f = finish <=< go where
  114. go :: [([Value], Value)] -> IO [([Value], Value, Elab.TypeError)]
  115. go [] = pure []
  116. go ((ixs, vl):faces) = do
  117. let env' = foldr (\(x, t) env -> env { names = Map.insert x t (names env) }) env (zip ns (zip (repeat VI) ixs))
  118. t <- try $ unifyTC env' (foldl (@@) f ixs) vl
  119. case t of
  120. Right _ -> go faces
  121. Left e -> ((ixs, vl, e):) <$> go faces
  122. finish [] = pure ()
  123. finish xs = throwIO $ WrongFaces f xs
  124. infer :: Env -> P.Exp -> IO (Term, Value)
  125. infer env (P.Span s e exp) =
  126. infer env exp
  127. `catch` \case
  128. InSpan s e err -> throwIO $ InSpan s e err
  129. err -> throwIO $ InSpan s e err
  130. `catch` \er -> throwIO $ InSpan s e (UnifyError er)
  131. infer env (P.Var s) =
  132. case Map.lookup s (names env) of
  133. Just (t, _) -> pure (Var s, t)
  134. Nothing -> throwIO (NotInScope s)
  135. infer env (P.App f x) = do
  136. (fun, ty) <- infer env f
  137. funt <- isPiOrPathType ty
  138. case funt of
  139. Left (_, dom, rng) -> do
  140. arg <- check env x dom
  141. let arg' = eval env arg
  142. pure (App fun arg, rng arg')
  143. Right (a, ai0, ai1) -> do
  144. arg <- check env x VI
  145. let arg' = eval env arg
  146. pure (PathP (quote a) (quote ai0) (quote ai1) fun arg, a @@ arg')
  147. infer env (P.Pi s d r) = do
  148. (dom, ty) <- infer env d
  149. case ty of
  150. VType -> pure VType
  151. VTypeω -> pure VTypeω
  152. _ -> throwIO . UnifyError $ NotSort ty
  153. let d' = eval env dom
  154. (rng, rng_t) <-
  155. infer env { names = Map.insert s (makeValueGluingSub d' s) (names env) } r
  156. case ty of
  157. VType -> pure VType
  158. VTypeω -> pure VTypeω
  159. _ -> throwIO . UnifyError $ NotSort ty
  160. pure (Pi s dom rng, rng_t)
  161. infer env (P.Sigma s d r) = do
  162. (dom, ty) <- infer env d
  163. rng_t <-
  164. case ty of
  165. VType -> pure VType
  166. VTypeω -> pure VTypeω
  167. _ -> throwIO . UnifyError $ NotSort ty
  168. let d' = eval env dom
  169. rng <- check env { names = Map.insert s (d', VVar s) (names env) } r rng_t
  170. pure (Sigma s dom rng, rng_t)
  171. infer env P.Type = pure (Type, VType)
  172. infer env P.Typeω = pure (Typeω, VTypeω)
  173. infer env P.I = pure (I, VTypeω)
  174. infer env P.I0 = pure (I0, VI)
  175. infer env P.I1 = pure (I1, VI)
  176. infer env (P.Cut e t) = do
  177. t <- check env t VType
  178. let t' = eval env t
  179. (, t') <$> check env e t'
  180. infer env (P.IAnd x y) = do
  181. x <- check env x VI
  182. y <- check env y VI
  183. pure (IAnd x y, VI)
  184. infer env (P.IOr x y) = do
  185. x <- check env x VI
  186. y <- check env y VI
  187. pure (IOr x y, VI)
  188. infer env P.Path =
  189. pure
  190. ( Lam "A" (quote index_t) $
  191. Lam "x" (App (Var "A") I0) $
  192. Lam "y" (App (Var "A") I1) $
  193. Path (Var "A") (Var "x") (Var "y")
  194. , VPi "A" index_t \a ->
  195. VPi "x" (a @@ VI0) \_ ->
  196. VPi "y" (a @@ VI1) (const VType))
  197. infer env P.PartialT =
  198. pure
  199. ( Lam "r" I $
  200. Lam "A" Type $
  201. Partial (Var "r") (Var "A")
  202. , VPi "I" VI \i ->
  203. VPi "A" VType (const VTypeω))
  204. infer env P.PartialP =
  205. pure
  206. ( Lam "r" I $
  207. Lam "A" (Partial (Var "r") Typeω) $
  208. PartialP (Var "r") (Var "A")
  209. , VPi "phi" VI \i ->
  210. VPi "A" (VPartial i VTypeω) (const VTypeω))
  211. infer env P.Comp = do
  212. let
  213. u_t a r = VPi "i" VI \i -> VPartial r (a @@ i)
  214. index_t :: Value
  215. index_t = VPi "_" VI (const VType)
  216. pure
  217. ( Lam "A" (quote index_t) $
  218. Lam "phi" I $
  219. Lam "u" (quote (u_t (VVar "A") (VVar "r"))) $
  220. Lam "a0" (Sub (App (Var "A") I0) (Var "phi") (App (Var "u") I0)) $
  221. Comp (Var "A") (Var "phi") (Var "u") (Var "a0")
  222. , VPi "A" index_t \a ->
  223. VPi "phi" VI \phi ->
  224. VPi "u" (u_t a phi) \u ->
  225. VPi "_" (VSub (a @@ VI0) phi (u @@ VI0)) \_ ->
  226. a @@ VI1
  227. )
  228. infer env P.SubT =
  229. pure
  230. ( Lam "A" Type $
  231. Lam "phi" I $
  232. Lam "u" (Partial (Var "phi") (Var "A")) $
  233. Sub (Var "A") (Var "phi") (Var "u")
  234. , VPi "A" VType \a ->
  235. VPi "phi" VI \phi ->
  236. VPi "_" (VPartial phi a) (const VType)
  237. )
  238. infer env P.GlueTy =
  239. pure
  240. ( Lam "A" Type $
  241. Lam "phi" I $
  242. Lam "T" (Partial (Var "phi") Type) $
  243. Lam "e" (PartialP (Var "phi") (quote (equiv (VVar "T") (VVar "A")))) $
  244. GlueTy (Var "A") (Var "phi") (Var "T") (Var "e")
  245. , VPi "A" VType \a ->
  246. VPi "phi" VI \phi ->
  247. VPi "T" (VPartial phi VType) \t ->
  248. VPi "e" (VPartialP phi (equiv t a)) \_ ->
  249. VType
  250. )
  251. infer env P.Glue =
  252. pure
  253. ( Lam "A" Type $
  254. Lam "phi" I $
  255. Lam "T" (Partial (Var "phi") Type) $
  256. Lam "e" (PartialP (Var "phi") (quote (equiv (VVar "T") (VVar "A")))) $
  257. Lam "t" (PartialP (Var "phi") (Var "T")) $
  258. Lam "a" (Var "A") $
  259. Glue (Var "A") (Var "phi") (Var "T") (Var "e") (Var "t") (Var "a")
  260. , VPi "A" VType \a ->
  261. VPi "phi" VI \phi ->
  262. VPi "T" (VPartial phi VType) \t ->
  263. VPi "e" (VPartialP phi (equiv t a)) \_ ->
  264. VPi "_" (VPartialP phi t) \_ ->
  265. VPi "_" a \_ -> VType
  266. )
  267. infer env P.Unglue =
  268. pure
  269. ( Lam "A" Type $
  270. Lam "phi" I $
  271. Lam "T" (Partial (Var "phi") Type) $
  272. Lam "e" (PartialP (Var "phi") (quote (equiv (VVar "T") (VVar "A")))) $
  273. Lam "g" (GlueTy (Var "A") (Var "phi") (Var "T") (Var "e")) $
  274. Unglue (Var "A") (Var "phi") (Var "T") (Var "e") (Var "g")
  275. , VPi "A" VType \a ->
  276. VPi "phi" VI \phi ->
  277. VPi "T" (VPartial phi VType) \t ->
  278. VPi "e" (VPartialP phi (equiv t a)) \e ->
  279. VPi "_" (VGlue a phi t e) \_ -> a
  280. )
  281. infer env P.Bool = pure (Bool, VType)
  282. infer env P.Tt = pure (Tt, VBool)
  283. infer env P.Ff = pure (Ff, VBool)
  284. infer env P.If =
  285. pure
  286. (Lam "P" (Pi "_" Bool Type) $
  287. Lam "x" (App (Var "P") Tt) $
  288. Lam "y" (App (Var "P") Ff) $
  289. Lam "b" Bool $
  290. If (Var "P") (Var "x") (Var "y") (Var "b")
  291. , VPi "P" (VPi "_" VBool (const VType)) \p ->
  292. VPi "_" (p @@ VTrue) \_ ->
  293. VPi "_" (p @@ VFalse) \_ ->
  294. VPi "x" VBool \x -> p @@ x)
  295. infer env (P.INot x) = (, VI) . INot <$> check env x VI
  296. infer env P.Lam{} = error "can't infer type for lambda"
  297. infer env (P.Let v t d b) = do
  298. ty <- check env t VTypeω
  299. let ty' = eval env ty
  300. d <- check env d ty'
  301. let d' = eval env d
  302. (b, t) <- infer env{ names = Map.insert v (ty', d') (names env) } b
  303. pure (Let v ty d b, t)
  304. infer env (P.Proj1 x) = do
  305. (t, ty) <- infer env x
  306. (_, d, _) <- isSigmaType ty
  307. pure (Proj1 t, d)
  308. infer env (P.Proj2 x) = do
  309. (t, ty) <- infer env x
  310. let t' = eval env t
  311. (_, _, r) <- isSigmaType ty
  312. pure (Proj2 t, r (proj1 t'))
  313. formulaToTm :: P.Formula -> P.Exp
  314. formulaToTm (P.Is0 i) = P.INot (P.Var i)
  315. formulaToTm (P.Is1 i) = P.Var i
  316. formulaToTm (P.And x y) = P.IAnd (formulaToTm x) (formulaToTm y)
  317. formulaToTm (P.Or x y) = P.IOr (formulaToTm x) (formulaToTm y)
  318. formulaToTm P.Top = P.I1
  319. formulaToTm P.Bot = P.I0
  320. checkFormula :: Env -> P.Formula -> IO ()
  321. checkFormula env P.Top = pure ()
  322. checkFormula env P.Bot = pure ()
  323. checkFormula env (P.And x y) = checkFormula env x *> checkFormula env y
  324. checkFormula env (P.Or x y) = checkFormula env x *> checkFormula env y
  325. checkFormula env (P.Is0 x) =
  326. case Map.lookup x (names env) of
  327. Just (ty, _) -> unifyTC env ty VI
  328. Nothing -> throwIO (NotInScope x)
  329. checkFormula env (P.Is1 x) =
  330. case Map.lookup x (names env) of
  331. Just (ty, _) -> unifyTC env ty VI
  332. Nothing -> throwIO (NotInScope x)
  333. index_t :: Value
  334. index_t = VPi "_" VI (const VTypeω)