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.

288 lines
8.4 KiB

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 qualified Data.Map.Strict as Map
  9. import Data.Typeable
  10. import qualified Presyntax as P
  11. import Syntax
  12. import Eval
  13. import Control.Monad
  14. import Systems
  15. import Data.Traversable
  16. import qualified Data.Set as Set
  17. import Data.Set (Set)
  18. import Data.Foldable
  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. check env exp (VSub a fm@(toFormula -> Just phi) el) = do
  35. tm <- check env exp a
  36. for (addFormula phi env) \env ->
  37. let tm' = eval env tm
  38. in unifyTC env tm' el
  39. pure (InclSub (quote a) (quote fm) (quote el) tm)
  40. check env (P.Lam s b) expected = do
  41. expc <- isPiOrPathType expected
  42. case expc of
  43. Left (_, d, r) -> do -- function
  44. bd <- check env { names = Map.insert s (makeValueGluingSub d s) (names env) } b (r (VVar s))
  45. pure (Lam s (quote d) bd)
  46. Right (a, x, y) -> do
  47. bd <- check env { names = Map.insert s (VI, VVar s) (names env) } b (a @@ VVar s)
  48. let t = Lam s I bd
  49. t' = eval env t
  50. checkBoundary env [s] t'
  51. [ ([VI0], x)
  52. , ([VI1], y)
  53. ]
  54. pure (PathI (quote a) (quote x) (quote y) s bd)
  55. check env (P.Let v t d b) expected = do
  56. ty <- check env t VType
  57. let ty' = eval env ty
  58. d <- check env d ty'
  59. let d' = eval env d
  60. b <- check env { names = Map.insert v (ty', d') (names env) } b expected
  61. pure (Let v (quote ty') d b)
  62. check env (P.Pair a b) expected = do
  63. (_, fst, snd) <- isSigmaType expected
  64. a <- check env a fst
  65. let a' = eval env a
  66. b <- check env b (snd a')
  67. pure (Pair a b)
  68. check env (P.Partial fs) ty = do
  69. let formula = orFormula (map fst fs)
  70. (extent, ty) <- isPartialType formula ty
  71. let ourFaces = Systems.faces formula
  72. extentFaces = Systems.faces extent
  73. unless (formula == extent) $
  74. throwIO $ IncompleteSystem formula extent
  75. let range = formulaToTm $ toDNF formula
  76. rangeTm <- check env range VI
  77. let rangeTy = eval env rangeTm
  78. ts <- for fs $ \(fn, tn) -> do
  79. tms <- for (addFormula fn env) \env -> check env tn ty
  80. pure (fn, head tms)
  81. fmap (System . FMap . Map.fromList) $ for ts \(fn, tn) -> do
  82. for ts \(fm, tm) -> do
  83. when (possible (fn `P.And` fm)) do
  84. for_ (addFormula (fn `P.And` fm) env) $ \env ->
  85. unifyTC (env) (eval env tn) (eval env tm)
  86. `catch` \e -> throwIO (IncompatibleFaces (fn, tn) (fm, tm) e)
  87. pure (fn, tn)
  88. check env exp expected = do
  89. (term, actual) <- infer env exp
  90. unifyTC env actual expected
  91. pure term
  92. makeValueGluingSub :: Value -> String -> (Value, Value)
  93. makeValueGluingSub ty@(VSub a phi a0) s = (ty, VOfSub a phi a0 (VVar s))
  94. makeValueGluingSub ty s = (ty, VVar s)
  95. addFormula :: P.Formula -> Env -> [Env]
  96. addFormula (P.And x y) = addFormula x >=> addFormula y
  97. addFormula (P.Or x y) = (++) <$> addFormula x <*> addFormula y
  98. addFormula P.Top = pure
  99. addFormula P.Bot = const []
  100. addFormula (P.Is0 x) = \env -> pure env{ names = Map.insert x (VI, VI0) (names env) }
  101. addFormula (P.Is1 x) = \env -> pure env{ names = Map.insert x (VI, VI1) (names env) }
  102. unifyTC :: Env -> Value -> Value -> IO ()
  103. unifyTC env a b = unify env a b `catch` \e -> const (throwIO (UnifyError (Mismatch a b))) (e :: UnifyError)
  104. checkBoundary :: Env -> [String] -> Value -> [([Value], Value)] -> IO ()
  105. checkBoundary env ns f = finish <=< go where
  106. go :: [([Value], Value)] -> IO [([Value], Value, Elab.TypeError)]
  107. go [] = pure []
  108. go ((ixs, vl):faces) = do
  109. let env' = foldr (\(x, t) env -> env { names = Map.insert x t (names env) }) env (zip ns (zip (repeat VI) ixs))
  110. t <- try $ unifyTC env' (foldl (@@) f ixs) vl
  111. case t of
  112. Right _ -> go faces
  113. Left e -> ((ixs, vl, e):) <$> go faces
  114. finish [] = pure ()
  115. finish xs = throwIO $ WrongFaces f xs
  116. infer :: Env -> P.Exp -> IO (Term, Value)
  117. infer env (P.Span s e exp) =
  118. infer env exp
  119. `catch` \case
  120. InSpan s e err -> throwIO $ InSpan s e err
  121. err -> throwIO $ InSpan s e err
  122. infer env (P.Var s) =
  123. case Map.lookup s (names env) of
  124. Just (t, _) -> pure (Var s, t)
  125. Nothing -> throwIO (NotInScope s)
  126. infer env (P.App f x) = do
  127. (fun, ty) <- infer env f
  128. funt <- isPiOrPathType ty
  129. case funt of
  130. Left (_, dom, rng) -> do
  131. arg <- check env x dom
  132. let arg' = eval env arg
  133. pure (App fun arg, rng arg')
  134. Right (a, ai0, ai1) -> do
  135. arg <- check env x VI
  136. let arg' = eval env arg
  137. pure (PathP (quote a) (quote ai0) (quote ai1) fun arg, a @@ arg')
  138. infer env (P.Pi s d r) = do
  139. dom <- check env d VType
  140. let d' = eval env dom
  141. rng <- check env { names = Map.insert s (d', VVar s) (names env) } r VType
  142. pure (Pi s dom rng, VType)
  143. infer env (P.Sigma s d r) = do
  144. dom <- check env d VType
  145. let d' = eval env dom
  146. rng <- check env { names = Map.insert s (d', VVar s) (names env) } r VType
  147. pure (Sigma s dom rng, VType)
  148. infer env P.Type = pure (Type, VType)
  149. infer env P.I = pure (I, VType)
  150. infer env P.I0 = pure (I0, VI)
  151. infer env P.I1 = pure (I1, VI)
  152. infer env (P.Cut e t) = do
  153. t <- check env t VType
  154. let t' = eval env t
  155. (, t') <$> check env e t'
  156. infer env (P.IAnd x y) = do
  157. x <- check env x VI
  158. y <- check env y VI
  159. pure (IAnd x y, VI)
  160. infer env (P.IOr x y) = do
  161. x <- check env x VI
  162. y <- check env y VI
  163. pure (IOr x y, VI)
  164. infer env P.Path = do
  165. pure
  166. ( Lam "A" (quote index_t) $
  167. Lam "x" (App (Var "A") I0) $
  168. Lam "y" (App (Var "A") I1) $
  169. Path (Var "A") (Var "x") (Var "y")
  170. , VPi "A" index_t \a ->
  171. VPi "x" (a @@ VI0) \_ ->
  172. VPi "y" (a @@ VI1) (const VType))
  173. infer env P.PartialT = do
  174. pure
  175. ( Lam "r" I $
  176. Lam "A" Type $
  177. Partial (Var "r") (Var "A")
  178. , VPi "I" VI \i ->
  179. VPi "A" VType (const VType))
  180. infer env P.Comp = do
  181. let u_t a r = VPi "i" VI \i -> VPartial r (a @@ i)
  182. pure
  183. ( Lam "A" (quote index_t) $
  184. Lam "phi" I $
  185. Lam "u" (quote (u_t (VVar "A") (VVar "r"))) $
  186. Lam "a0" (Sub (App (Var "A") I0) (Var "phi") (App (Var "u") I0)) $
  187. Comp (Var "A") (Var "phi") (Var "u") (Var "a0")
  188. , VPi "A" index_t \a ->
  189. VPi "phi" VI \phi ->
  190. VPi "u" (u_t a phi) \u ->
  191. VPi "_" (VSub (a @@ VI0) phi (u @@ VI0)) \_ ->
  192. a @@ VI1
  193. )
  194. infer env P.SubT = do
  195. pure
  196. ( Lam "A" Type $
  197. Lam "phi" I $
  198. Lam "u" (Partial (Var "phi") (Var "A")) $
  199. Sub (Var "A") (Var "phi") (Var "u")
  200. , VPi "A" VType \a ->
  201. VPi "phi" VI \phi ->
  202. VPi "_" (VPartial phi a) (const VType)
  203. )
  204. infer env (P.INot x) = (, VI) . INot <$> check env x VI
  205. infer env P.Lam{} = error "can't infer type for lambda"
  206. infer env (P.Let v t d b) = do
  207. ty <- check env t VType
  208. let ty' = eval env ty
  209. d <- check env d ty'
  210. let d' = eval env d
  211. (b, t) <- infer env{ names = Map.insert v (ty', d') (names env) } b
  212. pure (Let v ty d b, t)
  213. infer env (P.Proj1 x) = do
  214. (t, ty) <- infer env x
  215. (_, d, _) <- isSigmaType ty
  216. pure (Proj1 t, d)
  217. infer env (P.Proj2 x) = do
  218. (t, ty) <- infer env x
  219. let t' = eval env t
  220. (_, _, r) <- isSigmaType ty
  221. pure (Proj2 t, r (proj1 t'))
  222. formulaToTm :: P.Formula -> P.Exp
  223. formulaToTm (P.Is0 i) = P.INot (P.Var i)
  224. formulaToTm (P.Is1 i) = P.Var i
  225. formulaToTm (P.And x y) = P.IAnd (formulaToTm x) (formulaToTm y)
  226. formulaToTm (P.Or x y) = P.IOr (formulaToTm x) (formulaToTm y)
  227. formulaToTm P.Top = P.I1
  228. formulaToTm P.Bot = P.I0
  229. checkFormula :: Env -> P.Formula -> IO ()
  230. checkFormula env P.Top = pure ()
  231. checkFormula env P.Bot = pure ()
  232. checkFormula env (P.And x y) = checkFormula env x *> checkFormula env y
  233. checkFormula env (P.Or x y) = checkFormula env x *> checkFormula env y
  234. checkFormula env (P.Is0 x) =
  235. case Map.lookup x (names env) of
  236. Just (ty, _) -> unifyTC env ty VI
  237. Nothing -> throwIO (NotInScope x)
  238. checkFormula env (P.Is1 x) =
  239. case Map.lookup x (names env) of
  240. Just (ty, _) -> unifyTC env ty VI
  241. Nothing -> throwIO (NotInScope x)
  242. index_t :: Value
  243. index_t = VPi "_" VI (const VType)