| @ -0,0 +1 @@ | |||
| .stack-work | |||
| @ -0,0 +1,30 @@ | |||
| Copyright Abigail Magalhães (c) 2020 | |||
| All rights reserved. | |||
| Redistribution and use in source and binary forms, with or without | |||
| modification, are permitted provided that the following conditions are met: | |||
| * Redistributions of source code must retain the above copyright | |||
| notice, this list of conditions and the following disclaimer. | |||
| * Redistributions in binary form must reproduce the above | |||
| copyright notice, this list of conditions and the following | |||
| disclaimer in the documentation and/or other materials provided | |||
| with the distribution. | |||
| * Neither the name of Abigail Magalhães nor the names of other | |||
| contributors may be used to endorse or promote products derived | |||
| from this software without specific prior written permission. | |||
| THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | |||
| "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | |||
| LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | |||
| A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | |||
| OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |||
| SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | |||
| LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | |||
| DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | |||
| THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |||
| (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | |||
| OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |||
| @ -0,0 +1 @@ | |||
| # setoid | |||
| @ -0,0 +1,2 @@ | |||
| import Distribution.Simple | |||
| main = defaultMain | |||
| @ -0,0 +1,2 @@ | |||
| cradle: | |||
| stack: | |||
| @ -0,0 +1,36 @@ | |||
| name: setoid | |||
| version: 0.1.0.0 | |||
| -- synopsis: | |||
| -- description: | |||
| homepage: https://github.com/plt-hokusai/setoid#readme | |||
| license: BSD3 | |||
| license-file: LICENSE | |||
| author: Abigail Magalhães | |||
| maintainer: [email protected] | |||
| copyright: 2020 Abigail Magalhães | |||
| category: Web | |||
| build-type: Simple | |||
| cabal-version: >=1.10 | |||
| extra-source-files: README.md | |||
| executable setoid | |||
| hs-source-dirs: src | |||
| main-is: Main.hs | |||
| default-language: Haskell2010 | |||
| build-depends: mtl | |||
| , syb | |||
| , base | |||
| , text | |||
| , ghc-prim | |||
| , containers | |||
| , unordered-containers | |||
| other-modules: Syntax | |||
| , Syntax.Pretty | |||
| , Presyntax | |||
| , Evaluate | |||
| , Elaboration | |||
| , Value | |||
| , Presyntax.Lexer | |||
| , Presyntax.Parser | |||
| , Elaboration.Monad | |||
| @ -0,0 +1,253 @@ | |||
| {-# LANGUAGE NamedFieldPuns #-} | |||
| {-# LANGUAGE OverloadedStrings #-} | |||
| {-# LANGUAGE FlexibleContexts #-} | |||
| {-# LANGUAGE DerivingVia #-} | |||
| module Elaboration where | |||
| import Control.Monad.Except | |||
| import Control.Monad.Reader | |||
| import Control.Concurrent | |||
| import qualified Data.HashMap.Strict as HashMap | |||
| import qualified Data.IntMap.Strict as IntMap | |||
| import Data.Text (Text) | |||
| import Elaboration.Monad | |||
| import Evaluate | |||
| import Presyntax | |||
| import Syntax | |||
| import System.IO.Unsafe ( unsafeDupablePerformIO ) | |||
| import Value | |||
| elabNext :: MVar Int | |||
| elabNext = unsafeDupablePerformIO (newMVar 0) | |||
| {-# NOINLINE elabNext #-} | |||
| freshMeta :: Value -> ElabM Term | |||
| freshMeta expected = do | |||
| ctx <- ask | |||
| names <- getNames | |||
| thisMeta <- liftIO $ do | |||
| m <- modifyMVar elabNext $ \x -> pure (x + 1, x) | |||
| modifyMVar_ elabMetas $ pure . IntMap.insert m (Unsolved names expected) | |||
| pure m | |||
| pure $ NewMeta (MV thisMeta) (elabBound ctx) | |||
| insert :: Term -> VTy -> ElabM (Term, VTy) | |||
| insert f (VPi Im _ d r) = do | |||
| t <- freshMeta d | |||
| t_nf <- asks (flip evaluate t . elabEnv) | |||
| insert (App Im f t) (r $$ t_nf) | |||
| insert f x = pure (f, x) | |||
| insert' :: Term -> VTy -> ElabM (Term, VTy) | |||
| insert' t@(Lam Im _ _) ty = pure (t, ty) | |||
| insert' t ty = insert t ty | |||
| infer :: RawExpr -> ElabM (Term, VTy) | |||
| infer (RSrcPos start end expr) = local (\st -> st { elabSourcePos = (start, end) }) (infer expr) | |||
| infer (Rvar name) = ask >>= lookup where | |||
| lookup ElabState{elabNames, elabConstrs, elabLevel} = | |||
| case HashMap.lookup name elabNames of | |||
| Just (l, t) -> pure (Bv (lvl2Ix elabLevel l), t) | |||
| Nothing -> | |||
| case HashMap.lookup name elabConstrs of | |||
| Just t -> pure (Con name, t) | |||
| Nothing -> typeError (NotInScope name) | |||
| infer (Rapp p x y) = do | |||
| (x, x_ty) <- | |||
| infer x >>= \(x, x_ty) -> | |||
| case p of | |||
| Ex -> insert x x_ty | |||
| _ -> pure (x, x_ty) | |||
| (_, d, r) <- isPiType p x_ty | |||
| y <- check y d | |||
| y_nf <- asks (flip evaluate y . elabEnv) | |||
| pure (App p x y, r $$ y_nf) | |||
| infer (Rpi e v d r) = do | |||
| d <- check d VType | |||
| d_nf <- asks (flip evaluate d . elabEnv) | |||
| assumeLocal v d_nf $ do | |||
| r <- check r VType | |||
| pure (Pi e v d r, VType) | |||
| infer (Rsigma v d r) = do | |||
| d <- check d VType | |||
| d_nf <- asks (flip evaluate d . elabEnv) | |||
| assumeLocal v d_nf $ do | |||
| r <- check r VType | |||
| pure (Sigma v d r, VType) | |||
| infer (Rlet v t d b) = do | |||
| t <- check t VType | |||
| t_nf <- asks (flip evaluate t . elabEnv) | |||
| d <- check d t_nf | |||
| d_nf <- asks (flip evaluate d . elabEnv) | |||
| defineLocal v t_nf d_nf $ do | |||
| (b, ty) <- infer b | |||
| pure (Let v t d b, ty) | |||
| infer Rtype = pure (Type, VType) | |||
| infer Rhole = do | |||
| ty <- freshMeta VType | |||
| ty_nf <- asks (flip evaluate ty . elabEnv) | |||
| tm <- freshMeta ty_nf | |||
| pure (tm, ty_nf) | |||
| infer (Rlam p v t) = do | |||
| env <- asks elabEnv | |||
| lvl <- asks elabLevel | |||
| dom <- freshMeta VType | |||
| let dom_nf = evaluate env dom | |||
| assumeLocal v dom_nf $ do | |||
| (b, rng) <- infer t | |||
| pure (Lam p v b, VPi p v dom_nf (Closure env (quote (succ lvl) rng))) | |||
| infer Rtop = pure (Top, VType) | |||
| infer Runit = pure (Unit, VTop) | |||
| infer (Req a b) = do | |||
| t <- freshMeta VType | |||
| t_nf <- asks (flip evaluate t . elabEnv) | |||
| a <- check a t_nf | |||
| b <- check b t_nf | |||
| pure (Id t a b, VType) | |||
| infer Rrefl = | |||
| pure (Refl, forAll Im "A" VType $ \a -> forAll Im "x" a $ \x -> VEq a x x) | |||
| infer Rcoe = | |||
| pure ( Coe | |||
| , forAll Im "A" VType $ \a -> | |||
| forAll Im "B" VType $ \b -> | |||
| forAll Ex "_" (VEq VType a b) $ \_ -> | |||
| forAll Ex "_" a $ const b | |||
| ) | |||
| infer Rcong = | |||
| pure ( Cong | |||
| , forAll Im "A" VType $ \a -> | |||
| forAll Im "B" VType $ \b -> | |||
| forAll Im "x" a $ \x -> | |||
| forAll Im "y" a $ \y -> | |||
| forAll Ex "f" (forAll Ex "_" a (const b)) $ \f -> | |||
| forAll Ex "p" (VEq a x y) $ \_ -> | |||
| VEq b (vApp f Ex x) (vApp f Ex y) | |||
| ) | |||
| infer Rsym = | |||
| pure ( Sym | |||
| , forAll Im "A" VType $ \a -> forAll Im "x" a $ \x -> forAll Im "y" a $ \y -> forAll Ex "p" (VEq a x y) $ \_ -> VEq a y x | |||
| ) | |||
| infer (Rproj1 e) = do | |||
| (t, ty) <- infer e | |||
| (_, d, _) <- isSigmaType ty | |||
| pure (Proj1 t, d) | |||
| infer (Rproj2 e) = do | |||
| (t, ty) <- infer e | |||
| t_nf <- asks (flip evaluate t . elabEnv) | |||
| (_, _, r) <- isSigmaType ty | |||
| pure (Proj2 t, r $$ vProj1 t_nf) | |||
| infer c = do | |||
| t <- asks elabSwitches | |||
| when (t >= 128) $ | |||
| error $ "Unhandled case in type checker, stack overflew etc: " ++ show c | |||
| t <- freshMeta VType | |||
| t_nf <- asks (flip evaluate t . elabEnv) | |||
| c <- local (\e -> e { elabSwitches = succ (elabSwitches e)}) $ | |||
| check c t_nf | |||
| pure (c, t_nf) | |||
| check :: RawExpr -> VTy -> ElabM Term | |||
| check (RSrcPos start end expr) ty = local (\st -> st { elabSourcePos = (start, end) }) (check expr ty) | |||
| check (Rlam e v t) (VPi e' _ d r) | e == e' = do | |||
| level <- asks (unLvl . elabLevel) | |||
| assumeLocal v d $ | |||
| Lam e v <$> check t (r $$ vVar (Bound level)) | |||
| check t (VPi Im x d r) = do | |||
| level <- asks (unLvl . elabLevel) | |||
| assumeLocal x d $ | |||
| Lam Im x <$> check t (r $$ vVar (Bound level)) | |||
| check (Rlam e v t) ty = do | |||
| (_, d, r) <- isPiType e ty | |||
| level <- asks (unLvl . elabLevel) | |||
| assumeLocal v d $ | |||
| Lam e v <$> check t (r $$ vVar (Bound level)) | |||
| check (Rlet v t d b) ty = do | |||
| t <- check t VType | |||
| t_nf <- asks (flip evaluate t . elabEnv) | |||
| d <- check d t_nf | |||
| d_nf <- asks (flip evaluate d . elabEnv) | |||
| defineLocal v t_nf d_nf $ do | |||
| b <- check b ty | |||
| pure (Let v t d b) | |||
| check (Rpair a b) ty = do | |||
| (_, d, r) <- isSigmaType ty | |||
| a <- check a d | |||
| a_nf <- asks (flip evaluate a . elabEnv) | |||
| b <- check b (r $$ a_nf) | |||
| pure (Pair a b) | |||
| check e ty = do | |||
| (new, e_ty) <- uncurry insert =<< infer e | |||
| unify e_ty ty | |||
| `catchError` \_ -> do | |||
| l <- asks elabLevel | |||
| names <- getNames | |||
| typeError (NotEqual names (quote l (zonk ty)) (quote l (zonk e_ty))) | |||
| pure new | |||
| isPiType :: Plicity -> VTy -> ElabM (Text, VTy, Closure) | |||
| isPiType i = go . force where | |||
| go (VPi i' a b c) | |||
| | i == i' = pure (a, b, c) | |||
| go ty | not (flexible ty) = do | |||
| l <- asks elabLevel | |||
| names <- getNames | |||
| typeError (NotFunction names (quote l ty)) | |||
| go ty = do | |||
| env <- asks elabEnv | |||
| t <- freshMeta VType | |||
| let t_nf = evaluate env t | |||
| assumeLocal "α" t_nf $ do | |||
| r <- freshMeta VType | |||
| unify ty (VPi i "α" t_nf (Closure env r)) | |||
| pure ("α", t_nf, Closure env r) | |||
| isSigmaType :: VTy -> ElabM (Text, VTy, Closure) | |||
| isSigmaType = go . force where | |||
| go (VSigma a b c) = pure (a, b, c) | |||
| go ty = do | |||
| env <- asks elabEnv | |||
| t <- freshMeta VType | |||
| let t_nf = evaluate env t | |||
| assumeLocal "α" t_nf $ do | |||
| r <- freshMeta VType | |||
| unify ty (VSigma "α" t_nf (Closure env r)) | |||
| pure ("α", t_nf, Closure env r) | |||
| @ -0,0 +1,97 @@ | |||
| {-# LANGUAGE FlexibleContexts #-} | |||
| {-# LANGUAGE DerivingVia #-} | |||
| module Elaboration.Monad where | |||
| import Control.Monad.Except | |||
| import Control.Monad.Reader | |||
| import Control.Applicative | |||
| import qualified Data.HashMap.Strict as HashMap | |||
| import qualified Data.Sequence as Seq | |||
| import Data.HashMap.Strict (HashMap) | |||
| import Data.Text (Text) | |||
| import Syntax | |||
| import Value | |||
| data ElabState = | |||
| ElabState | |||
| { elabEnv :: {-# UNPACK #-} !Env | |||
| , elabLevel :: {-# UNPACK #-} !Level | |||
| , elabSwitches :: {-# UNPACK #-} !Int | |||
| , elabNames :: HashMap Text (Level, VTy) | |||
| , elabConstrs :: HashMap Text VTy | |||
| , elabBound :: [BoundDef] | |||
| , elabSourcePos :: ((Int, Int), (Int, Int)) | |||
| } | |||
| deriving (Eq) | |||
| emptyElabState :: ElabState | |||
| emptyElabState = ElabState emptyEnv (Lvl 0) 0 mempty mempty [] ((0, 0), (0, 0)) | |||
| getNames :: MonadReader ElabState m => m [Text] | |||
| getNames = asks (map go . elabBound) where | |||
| go (BDBound n) = n | |||
| go (BDDefined n) = n | |||
| data ElabError | |||
| = NotInScope Text | |||
| | NotFunction [Text] Term | |||
| | NotEqual [Text] Term Term | |||
| | CantSolveMeta [Text] Term Term | |||
| deriving (Show) | |||
| data ProgError | |||
| = ProgError { peErr :: ElabError | |||
| , peSL :: !Int | |||
| , peSC :: !Int | |||
| , peEL :: !Int | |||
| , peEC :: !Int | |||
| } | |||
| deriving (Show) | |||
| newtype ElabM a | |||
| = ElabM { runElab :: ElabState -> IO (Either [ProgError] a) } | |||
| deriving | |||
| ( Functor | |||
| , Applicative | |||
| , Monad | |||
| , Alternative | |||
| , MonadPlus | |||
| , MonadReader ElabState | |||
| , MonadError [ProgError] | |||
| , MonadIO | |||
| ) | |||
| via ReaderT ElabState (ExceptT [ProgError] IO) | |||
| typeError :: ElabError -> ElabM a | |||
| typeError err = do | |||
| (s, e) <- asks elabSourcePos | |||
| throwError [uncurry (uncurry (ProgError err) s) e] | |||
| assumeLocal :: Text -> VTy -> ElabM a -> ElabM a | |||
| assumeLocal name tipe = local go where | |||
| go r = | |||
| r { elabLevel = succ (elabLevel r) | |||
| , elabNames = HashMap.insert name (elabLevel r, tipe) (elabNames r) | |||
| , elabEnv = (elabEnv r) { | |||
| locals = VGlued (HVar (Bound (unLvl (elabLevel r)))) mempty Nothing | |||
| Seq.<| locals (elabEnv r) | |||
| } | |||
| , elabBound = BDBound name:elabBound r | |||
| } | |||
| defineLocal :: Text -> VTy -> Value -> ElabM a -> ElabM a | |||
| defineLocal name tipe val = local go where | |||
| go r = | |||
| r { elabLevel = succ (elabLevel r) | |||
| , elabNames = HashMap.insert name (elabLevel r, tipe) (elabNames r) | |||
| , elabEnv = (elabEnv r) { | |||
| locals = val Seq.<| locals (elabEnv r) | |||
| } | |||
| , elabBound = BDDefined name:elabBound r | |||
| } | |||
| @ -0,0 +1,441 @@ | |||
| {-# LANGUAGE FlexibleContexts #-} | |||
| {-# LANGUAGE LambdaCase #-} | |||
| {-# LANGUAGE ViewPatterns #-} | |||
| {-# LANGUAGE BlockArguments #-} | |||
| {-# LANGUAGE OverloadedStrings #-} | |||
| module Evaluate where | |||
| import qualified Control.Exception as Exc | |||
| import Control.Monad.Except | |||
| import Control.Monad.Reader | |||
| import Control.Concurrent | |||
| import qualified Data.IntMap.Strict as IntMap | |||
| import qualified Data.Sequence as Seq | |||
| import qualified Data.Text as T | |||
| import Elaboration.Monad | |||
| import GHC.Stack (HasCallStack) | |||
| import Generics.SYB (mkT, everywhere) | |||
| import Syntax | |||
| import System.IO.Unsafe | |||
| import Value | |||
| import Data.Foldable | |||
| import Syntax.Pretty (showWithPrec) | |||
| evaluate :: HasCallStack => Env -> Term -> Value | |||
| evaluate env (Var (Bound i)) = | |||
| case Seq.lookup i (locals env) of | |||
| Just x -> x | |||
| Nothing -> error $ "Variable of index " ++ show i ++ " not in scope" | |||
| evaluate _ (Con t) = VGlued (HCon t) mempty Nothing | |||
| evaluate _ Type = VType | |||
| evaluate env (Pi p t d r) = VPi p t (evaluate env d) (Closure env r) | |||
| evaluate env (Lam p t b) = VLam p t (Closure env b) | |||
| evaluate env (App p f x) = vApp (evaluate env f) p (evaluate env x) | |||
| evaluate env (Sigma t d r) = VSigma t (evaluate env d) (Closure env r) | |||
| evaluate env (Pair a b) = VPair (evaluate env a) (evaluate env b) | |||
| evaluate env (Proj1 a) = vProj1 (evaluate env a) | |||
| evaluate env (Proj2 a) = vProj2 (evaluate env a) | |||
| evaluate _ (Meta m) = VGlued (HMeta m) mempty Nothing | |||
| evaluate env (NewMeta m mask) = VGlued (HMeta m) (getVals (locals env) mask) Nothing where | |||
| getVals Seq.Empty [] = Seq.Empty | |||
| getVals (v Seq.:<| seq) (BDBound _:bds) = AppEx v Seq.:<| getVals seq bds | |||
| getVals (_ Seq.:<| seq) (BDDefined _:bds) = getVals seq bds | |||
| evaluate _ Top = VTop | |||
| evaluate _ Unit = VUnit | |||
| evaluate _ Refl = VGlued HRefl mempty Nothing | |||
| evaluate _ Coe = | |||
| function Im (T.pack "A") $ \a -> | |||
| function Im (T.pack "B") $ \b -> | |||
| function Ex (T.pack "p") $ \p -> | |||
| function Ex (T.pack "x") $ \x -> | |||
| vCoe a b p x | |||
| evaluate _ Cong = | |||
| function Im (T.pack "A") $ \a -> | |||
| function Im (T.pack "B") $ \b -> | |||
| function Im (T.pack "x") $ \x -> | |||
| function Im (T.pack "y") $ \y -> | |||
| function Ex (T.pack "f") $ \f -> | |||
| function Ex (T.pack "p") $ \p -> | |||
| vCong a b x y f p | |||
| evaluate _ Sym = | |||
| function Im (T.pack "A") $ \a -> | |||
| function Im (T.pack "x") $ \x -> | |||
| function Im (T.pack "y") $ \y -> | |||
| function Ex (T.pack "p") $ \p -> | |||
| vSym a x y p | |||
| evaluate e (Let _ _ c d) = evaluate e' d where | |||
| e' = e { locals = evaluate e c Seq.:<| locals e } | |||
| evaluate env (Id a b c) = vId (evaluate env a) (evaluate env b) (evaluate env c) | |||
| vId :: Value -> Value -> Value -> Value | |||
| vId kind a b = | |||
| let stuck = VEq kind a b | |||
| solve = VEqG kind a b | |||
| never = solve vBottom | |||
| always = solve VTop | |||
| in | |||
| case force kind of | |||
| VType -> | |||
| case (a, b) of | |||
| (VTop, VTop) -> always | |||
| (VType, VType) -> always | |||
| (VEqG _ _ _ a, b) -> vId VType a b | |||
| (a, VEqG _ _ _ b) -> vId VType a b | |||
| (VEq a _ _, VEq b _ _) -> vId VType a b | |||
| (VPi i _ d r, VPi i' _ d' r') | |||
| | i == i' -> | |||
| solve $ | |||
| exists "p" (vId VType d d') $ \p -> | |||
| forAll Ex "x" d $ \x -> | |||
| vId VType (r $$ x) (r' $$ vCoe d d' p x) | |||
| | otherwise -> never | |||
| (VSigma _ d r, VSigma _ d' r') -> | |||
| solve $ | |||
| exists "p" (vId VType d d') $ \p -> | |||
| forAll Ex "x" d $ \x -> | |||
| vId VType (r $$ x) (r' $$ vCoe d d' p x) | |||
| (VNe _ _, _) -> stuck | |||
| (_, VNe _ _) -> stuck | |||
| _ -> never | |||
| VTop -> always | |||
| VPi i t dom cod -> | |||
| solve $ forAll i t dom \vl -> vId (cod $$ vl) (vApp a i vl) (vApp b i vl) | |||
| VSigma t dom cod -> | |||
| -- a = (x, p) | |||
| -- b = (y, q) | |||
| -- (a, b) ≡ (c, d) : (x : A) * P x | |||
| -- ~> (path : a == c) * coe (cong A Type P path) b == d | |||
| let x = vProj1 a | |||
| y = vProj1 b | |||
| p = vProj2 a | |||
| q = vProj2 b | |||
| in solve $ | |||
| exists t (vId dom x y) $ \pr -> | |||
| vId (cod $$ y) (vCoe (cod $$ x) (cod $$ y) (vCong dom VType x y (function Ex (T.pack "x") (cod $$)) pr) p) q | |||
| VEq{} -> solve VTop | |||
| _ -> stuck | |||
| vBottom :: Value | |||
| vBottom = forAll Im "A" VType id | |||
| vCoe :: VTy -> VTy -> Value -> Value -> Value | |||
| -- vCoe _ _ (VGlued HRefl _ _) element = element | |||
| vCoe (VPi i _ d r) ty2@(VPi i' _ d' r') p f | |||
| | i /= i' = vApp p Ex ty2 | |||
| | otherwise = | |||
| function i "x" $ \x -> | |||
| let p1 = vProj1 p -- d == d' | |||
| p2 = vProj2 p -- (x : A) -> r x == r' (coe p1 x) | |||
| x0 = vCoe d' d (vSym VType d d' p1) x | |||
| in vCoe (r $$ x0) (r' $$ x) (vApp p2 Ex x0) (vApp f i x0) | |||
| vCoe tyA tyB proof element = splitFibration tyA tyB $ VGlued HCoe (Seq.fromList spine) Nothing where | |||
| spine = [AppIm tyA, AppIm tyB, AppEx proof, AppEx element] | |||
| -- Types are split fibrations | |||
| -- coe {A} {A} p x = x even when p /= refl | |||
| splitFibration tA tB vstuck = unsafeDupablePerformIO $ do | |||
| old <- readMVar elabMetas | |||
| t <- runElab (unify tA tB) emptyElabState | |||
| case t of | |||
| Left _ -> do | |||
| swapMVar elabMetas old | |||
| pure vstuck | |||
| Right _ -> pure element | |||
| vCong :: Value -> Value -> Value -> Value -> Value -> Value -> Value | |||
| vCong _a c _x _y g (force -> VGlued HCong (toList -> [AppIm a, AppIm _b, AppIm x, AppIm y, AppEx f, AppEx p]) _) = | |||
| VGlued HCong (Seq.fromList [AppIm a, AppIm c, AppIm x, AppIm y, AppEx (function Ex "x" (vApp g Ex . vApp f Ex)), AppEx p]) Nothing | |||
| vCong _a b _x _ f (force -> VGlued HRefl (toList -> [AppIm _, AppIm x]) _) = | |||
| VGlued HRefl (Seq.fromList [AppIm b, AppIm (vApp f Ex x)]) Nothing | |||
| vCong a b x y f p = | |||
| VGlued HCong (Seq.fromList [AppIm a, AppIm b, AppIm x, AppIm y, AppEx f, AppEx p]) Nothing | |||
| vSym :: Value -> Value -> Value -> Value -> Value | |||
| vSym a _ y (VGlued HRefl _ Nothing) = | |||
| VGlued HRefl (Seq.fromList [AppIm a, AppIm y]) Nothing | |||
| vSym _ _ _ (VGlued HSym (toList -> [_a, _y, _x, AppEx p]) Nothing) = p | |||
| vSym a x y p = VGlued HSym (Seq.fromList [AppIm a, AppIm x, AppIm y, AppEx p]) Nothing | |||
| vApp :: HasCallStack => Value -> Plicity -> Value -> Value | |||
| vApp (VGlued x s v) p r = VGlued x (s Seq.|> thing) (fmap (\v -> vApp v p r) v) where | |||
| thing = | |||
| case p of | |||
| Ex -> AppEx r | |||
| Im -> AppIm r | |||
| vApp (VLam _ _ c) _ a = c $$ a | |||
| vApp _fun _plic _arg = error "invalid application" | |||
| vProj1 :: Value -> Value | |||
| vProj1 (VPair a _) = a | |||
| vProj1 x = VProj1 x | |||
| vProj2 :: Value -> Value | |||
| vProj2 (VPair _ a) = a | |||
| vProj2 x = VProj2 x | |||
| ($$) :: HasCallStack => Closure -> Value -> Value | |||
| Closure e t $$ v = evaluate e' t where | |||
| e' = e { locals = v Seq.:<| locals e } | |||
| ClMeta (MetaFun f) $$ v = f v | |||
| forAll :: Plicity -> T.Text -> Value -> (Value -> Value) -> Value | |||
| forAll i t d = VPi i t d . ClMeta . MetaFun | |||
| exists :: T.Text -> Value -> (Value -> Value) -> Value | |||
| exists t d = VSigma t d . ClMeta . MetaFun | |||
| function :: Plicity -> T.Text -> (Value -> Value) -> Value | |||
| function i t = VLam i t . ClMeta . MetaFun | |||
| quote :: HasCallStack => Level -> Value -> Term | |||
| quote _ VType = Type | |||
| quote l (VPi p t d r) = Pi p t (quote l d) (quote (succ l) (r $$ vVar (Bound (unLvl l)))) | |||
| quote l (VLam p t b) = Lam p t (quote (succ l) (b $$ vVar (Bound (unLvl l)))) | |||
| quote l (VSigma t d r) = Sigma t (quote l d) (quote (succ l) (r $$ vVar (Bound (unLvl l)))) | |||
| quote l (VPair a b) = Pair (quote l a) (quote l b) | |||
| quote l (VProj1 a) = Proj1 (quote l a) | |||
| quote l (VProj2 a) = Proj2 (quote l a) | |||
| quote _ VTop = Top | |||
| quote _ VUnit = Unit | |||
| quote l (VEq a b c) = Id (quote l a) (quote l b) (quote l c) | |||
| -- quote l (VEqG _ _ _ d) = quote l d | |||
| quote l (VEqG a b c _) = Id (quote l a) (quote l b) (quote l c) | |||
| quote l (VGlued v s _) = foldl app v' s where | |||
| v' = case v of | |||
| HVar (Bound i) -> Bv (lvl2Ix l (Lvl i)) | |||
| HCon t -> Con t | |||
| HMeta m -> Meta m | |||
| HRefl -> Refl | |||
| HCoe -> Coe | |||
| HCong -> Cong | |||
| HSym -> Sym | |||
| app f (AppEx t) = App Ex f (quote l t) | |||
| app f (AppIm t) = App Im f (quote l t) | |||
| app f SProj1 = Proj1 f | |||
| app f SProj2 = Proj2 f | |||
| force :: Value -> Value | |||
| force = unsafeDupablePerformIO . go where | |||
| go stuck@(VGlued (HMeta (MV m)) sp Nothing) = do | |||
| t <- readMVar elabMetas | |||
| case IntMap.lookup m t of | |||
| Just (Solved vl) -> go $ foldl vAppSp vl sp | |||
| _ -> pure stuck | |||
| go (VGlued _ _ (Just vl)) = go vl | |||
| go x = pure x | |||
| vAppSp :: Value -> SpineThing -> Value | |||
| vAppSp vl (AppEx f) = vApp vl Ex f | |||
| vAppSp vl (AppIm f) = vApp vl Im f | |||
| vAppSp vl SProj1 = vProj1 vl | |||
| vAppSp vl SProj2 = vProj2 vl | |||
| zonk :: Value -> Value | |||
| zonk (VLam vis var body) = VLam vis var (ClMeta (MetaFun (\v -> zonk (body $$ v)))) | |||
| zonk (VPi vis var dom body) = VPi vis var (zonk dom) (ClMeta (MetaFun (\v -> zonk (body $$ v)))) | |||
| zonk (VSigma var dom body) = VSigma var (zonk dom) (ClMeta (MetaFun (\v -> zonk (body $$ v)))) | |||
| zonk t = everywhere (mkT force) t | |||
| unify :: VTy -> VTy -> ElabM () | |||
| unify a b = asks elabLevel >>= flip go (a, b) where | |||
| go, go' :: Level -> (VTy, VTy) -> ElabM () | |||
| go' l (VGlued h sp x, VGlued h' sp' y) | |||
| | h == h' = goSpine l sp sp' | |||
| | Just x <- x, Just y <- y = go l (x, y) | |||
| -- flexible head (solve meta) | |||
| go' l (VGlued (HMeta m) sp _, y) = solveMeta m sp y | |||
| go' _ (x, VGlued (HMeta m) sp _) = solveMeta m sp x | |||
| -- rigid heads (compare unfolding) | |||
| go' l (VGlued _ _ (Just x), y) = go l (x, y) | |||
| go' l (x, VGlued _ _ (Just y)) = go l (x, y) | |||
| go' _ (VType, VType) = pure () | |||
| go' _ (VTop, VTop) = pure () | |||
| go' _ (VUnit, VUnit) = pure () | |||
| go' l (VPi i _ d r, VPi i' _ d' r') | i == i' = do | |||
| go l (d, d') | |||
| let i = unLvl l | |||
| go (succ l) (r $$ vVar (Bound i), r' $$ vVar (Bound i)) | |||
| go' l (VSigma _ d r, VSigma _ d' r') = do | |||
| go l (d, d') | |||
| let i = unLvl l | |||
| go (succ l) (r $$ vVar (Bound i), r' $$ vVar (Bound i)) | |||
| go' l (VLam i _ r, VLam i' _ r') | i == i' = do | |||
| let i = unLvl l | |||
| go (succ l) (r $$ vVar (Bound i), r' $$ vVar (Bound i)) | |||
| go' l (VLam p _ r, t) = do | |||
| let i = unLvl l | |||
| go (succ l) (r $$ vVar (Bound i), vApp t p (vVar (Bound i))) | |||
| go' l (r, VLam p _ t) = do | |||
| let i = unLvl l | |||
| go (succ l) (vApp r p (vVar (Bound i)), t $$ vVar (Bound i)) | |||
| go' l (VEqG a b c _, VEqG a' b' c' _) = go l (a, a') *> go l (b, b') *> go l (c, c') | |||
| go' l (VEq a b c, VEqG a' b' c' _) = go l (a, a') *> go l (b, b') *> go l (c, c') | |||
| go' l (VEqG a b c _, VEq a' b' c') = go l (a, a') *> go l (b, b') *> go l (c, c') | |||
| go' l (VEq a b c, VEq a' b' c') = go l (a, a') *> go l (b, b') *> go l (c, c') | |||
| go' l (VEqG _ _ _ a, b) = go l (a, b) | |||
| go' l (a, VEqG _ _ _ b) = go l (a, b) | |||
| go' l (VProj1 a, VProj1 b) = go l (a, b) | |||
| go' l (VProj2 a, VProj2 b) = go l (a, b) | |||
| go' l (VPair a b, VPair a' b') = go l (a, a') >> go l (b, b') | |||
| go' l (a, b) = do | |||
| ns <- getNames | |||
| typeError (NotEqual ns (quote l a) (quote l b)) | |||
| go l (a, b) = go' l (force a, force b) | |||
| goSpine _ Seq.Empty Seq.Empty = pure () | |||
| goSpine l (AppEx x Seq.:<| xs) (AppEx y Seq.:<| ys) = do | |||
| go l (x, y) | |||
| goSpine l xs ys | |||
| goSpine l (AppIm x Seq.:<| xs) (AppIm y Seq.:<| ys) = do | |||
| go l (x, y) | |||
| goSpine l xs ys | |||
| goSpine l (x Seq.:<| xs) (y Seq.:<| ys) | x == y = goSpine l xs ys | |||
| goSpine l _ _ = do | |||
| ns <- getNames | |||
| typeError (NotEqual ns (quote l a) (quote l b)) | |||
| solveMeta :: HasCallStack => MetaVar -> Seq.Seq SpineThing -> VTy -> ElabM () | |||
| solveMeta (MV meta) spine rhs = | |||
| do | |||
| level <- asks elabLevel | |||
| pren <- invert level spine | |||
| rhs <- rename (MV meta) pren rhs | |||
| let solution = evaluate emptyEnv (lams (dom pren) rhs) | |||
| -- need to deepSeq solutions here | |||
| -- no deepSeq? no problem | |||
| liftIO $ Exc.evaluate (length (show solution)) | |||
| liftIO . modifyMVar_ elabMetas $ pure . IntMap.insert meta (Solved solution) | |||
| `catchError` \case | |||
| [] -> do | |||
| level <- asks elabLevel | |||
| names <- getNames | |||
| typeError (CantSolveMeta names (quote level (VGlued (HMeta (MV meta)) spine Nothing)) (quote level rhs)) | |||
| cs -> throwError cs | |||
| elabMetas :: MVar (IntMap.IntMap Meta) | |||
| elabMetas = unsafeDupablePerformIO (newMVar mempty) | |||
| {-# NOINLINE elabMetas #-} | |||
| lams :: Level -> Term -> Term | |||
| lams l = go (Lvl 0) where | |||
| go x t | x == l = t | |||
| go x t = Lam Ex (T.pack ("x" ++ show (unLvl x))) $ go (succ x) t | |||
| data PartialRen | |||
| = PRen { dom :: {-# UNPACK #-} !Level | |||
| , rng :: {-# UNPACK #-} !Level | |||
| , sub :: IntMap.IntMap Level | |||
| } | |||
| deriving (Eq, Show, Ord) | |||
| liftRen :: PartialRen -> PartialRen | |||
| liftRen (PRen d r s) = PRen (succ d) (succ r) (IntMap.insert (unLvl r) d s) | |||
| invert :: Level -> Seq.Seq SpineThing -> ElabM PartialRen | |||
| invert gamma spine = | |||
| do | |||
| (dom, ren) <- go spine | |||
| pure (PRen dom gamma ren) | |||
| where | |||
| go Seq.Empty = pure (Lvl 0, mempty) | |||
| go (sp Seq.:|> AppEx t) = do | |||
| (dom, ren) <- go sp | |||
| case force t of | |||
| VGlued (HVar (Bound l)) Seq.Empty _ | |||
| | IntMap.notMember l ren -> pure (succ dom, IntMap.insert l dom ren) | |||
| _ -> throwError [] | |||
| go (_ Seq.:|> _) = throwError [] | |||
| rename :: HasCallStack => MetaVar -> PartialRen -> Value -> ElabM Term | |||
| rename meta pren = go pren where | |||
| go :: HasCallStack => PartialRen -> Value -> ElabM Term | |||
| go pren (VGlued (HMeta m) sp _) | |||
| | m == meta = throwError [] | |||
| | otherwise = goSp pren (Meta m) sp | |||
| go pren (VGlued (HVar (Bound m)) sp _) = | |||
| case IntMap.lookup m (sub pren) of | |||
| Just v -> goSp pren (Bv (lvl2Ix (dom pren) v)) sp | |||
| Nothing -> throwError [] | |||
| go pren (VGlued h sp _) = goHead h >>= \h -> goSp pren h sp where | |||
| goHead HRefl = pure Refl | |||
| goHead HCong = pure Cong | |||
| goHead HCoe = pure Coe | |||
| goHead HSym = pure Sym | |||
| go pren (VPi p t d r) = Pi p t <$> go pren d <*> go (liftRen pren) (r $$ vVar (Bound (unLvl (rng pren)))) | |||
| go pren (VLam p t x) = Lam p t <$> go (liftRen pren) (x $$ vVar (Bound (unLvl (rng pren)))) | |||
| go _ VType = pure Type | |||
| go _ VTop = pure Top | |||
| go _ VUnit = pure Unit | |||
| go pren (VSigma t d r) = Sigma t <$> go pren d <*> go (liftRen pren) (r $$ vVar (Bound (unLvl (rng pren)))) | |||
| go pren (VPair a b) = Pair <$> go pren a <*> go pren b | |||
| go pren (VProj1 a) = Proj1 <$> go pren a | |||
| go pren (VProj2 a) = Proj2 <$> go pren a | |||
| go pren (VEq a b c) = Id <$> go pren a <*> go pren b <*> go pren c | |||
| go pren (VEqG _ _ _ d) = go pren d | |||
| -- go pren x = error (show x) | |||
| goSp _ t Seq.Empty = pure t | |||
| goSp pren t (sp Seq.:|> AppEx tm) = App Ex <$> goSp pren t sp <*> go pren tm | |||
| goSp pren t (sp Seq.:|> AppIm tm) = App Im <$> goSp pren t sp <*> go pren tm | |||
| goSp pren t (sp Seq.:|> SProj1) = Proj1 <$> goSp pren t sp | |||
| goSp pren t (sp Seq.:|> SProj2) = Proj2 <$> goSp pren t sp | |||
| @ -0,0 +1,61 @@ | |||
| {-# LANGUAGE LambdaCase #-} | |||
| module Main where | |||
| import Presyntax.Parser | |||
| import System.Environment (getArgs) | |||
| import Elaboration | |||
| import Elaboration.Monad | |||
| import Control.Monad.Reader | |||
| import Syntax | |||
| import Evaluate (elabMetas, zonk, evaluate, quote) | |||
| import Syntax.Pretty | |||
| import Data.Foldable | |||
| import Control.Concurrent | |||
| import qualified Data.IntMap.Strict as Map | |||
| import Value (Meta(Solved, Unsolved)) | |||
| main :: IO () | |||
| main = do | |||
| [path] <- getArgs | |||
| text <- readFile path | |||
| x <- | |||
| case parseString body text of | |||
| Left e -> error (show e) | |||
| Right x -> pure x | |||
| swapMVar elabMetas mempty | |||
| swapMVar elabNext 0 | |||
| t <- runElab ((,) <$> infer x <*> ask) emptyElabState | |||
| case t of | |||
| Left e -> traverse_ (putStrLn . showProgError text) e | |||
| Right ((x, t), e) -> do | |||
| metas <- readMVar elabMetas | |||
| for_ (Map.toList metas) $ \case | |||
| (n, Unsolved names v) -> | |||
| putStrLn $ '?':show n ++ " : " ++ showWithPrec names 0 (quote (Lvl (length names)) (zonk v)) "" ++ " = ? " | |||
| (n, Solved v) -> | |||
| putStrLn $ '?':show n ++ " = " ++ showTerm 0 (quote (Lvl 0) v) "" | |||
| putStrLn . flip id "" $ showTerm 0 x | |||
| putStrLn . flip id "" $ showString "Type: " . showTerm 0 (quote (Lvl 0) (zonk t)) | |||
| let t = quote (Lvl 0) . zonk . evaluate (elabEnv e) $ x | |||
| putStrLn $ "Normal form: " ++ showTerm 0 t "" | |||
| showProgError :: String -> ProgError -> String | |||
| showProgError text (ProgError e sl sc el ec) | |||
| | sl == el, sl < length (lines text) = | |||
| let code = lines text | |||
| line = code !! sl | |||
| linum = show sl | |||
| caretLine = replicate (length linum) ' ' ++ " | " ++ replicate sc ' ' ++ "^" ++ replicate (ec - sc) '~' | |||
| paddedLine = replicate (length linum) ' ' ++ " | " | |||
| in unlines [ paddedLine | |||
| , linum ++ " | " ++ line | |||
| , caretLine | |||
| , showElabError e "" | |||
| ] | |||
| | otherwise = showElabError e "" | |||
| @ -0,0 +1,29 @@ | |||
| module Presyntax where | |||
| import Data.Text (Text) | |||
| import Syntax (Plicity) | |||
| data RawExpr | |||
| = Rvar Text | |||
| | Rapp Plicity RawExpr RawExpr | |||
| | Rlam Plicity Text RawExpr | |||
| | Rpi Plicity Text RawExpr RawExpr | |||
| | Rlet Text RawExpr RawExpr RawExpr | |||
| | Rtype | |||
| | Rhole | |||
| | Rtop | Runit | |||
| | Rbot | |||
| | Req RawExpr RawExpr | |||
| | Rrefl | |||
| | Rcoe | |||
| | Rcong | |||
| | Rsym | |||
| | Rsigma Text RawExpr RawExpr | |||
| | Rpair RawExpr RawExpr | |||
| | Rproj1 RawExpr | |||
| | Rproj2 RawExpr | |||
| | RSrcPos (Int, Int) (Int, Int) RawExpr | |||
| deriving (Eq, Show, Ord) | |||
| @ -0,0 +1,172 @@ | |||
| {-# LANGUAGE BangPatterns #-} | |||
| module Presyntax.Lexer where | |||
| import Data.Text (Text) | |||
| import Data.Char | |||
| import qualified Data.Text as T | |||
| {- HLINT ignore -} | |||
| data TokenClass | |||
| = Tok_var Text | |||
| | Tok_lambda | |||
| | Tok_type | |||
| | Tok_let | |||
| | Tok_in | |||
| -- Operations on equality | |||
| | Tok_coe | |||
| | Tok_cong | |||
| | Tok_refl | |||
| | Tok_sym | |||
| | Tok_proj1 | |||
| | Tok_proj2 | |||
| | Tok_top | |||
| | Tok_oparen | |||
| | Tok_cparen | |||
| | Tok_obrace | |||
| | Tok_cbrace | |||
| | Tok_arrow | |||
| | Tok_times | |||
| | Tok_colon | |||
| | Tok_comma | |||
| | Tok_semi | |||
| | Tok_equal | |||
| | Tok_under | |||
| | Tok_equiv | |||
| deriving (Eq, Show, Ord) | |||
| data Token | |||
| = Token { tokLine :: {-# UNPACK #-} !Int | |||
| , tokCol :: {-# UNPACK #-} !Int | |||
| , tokSOff :: {-# UNPACK #-} !Int | |||
| , tokOff :: {-# UNPACK #-} !Int | |||
| , tokClass :: !TokenClass | |||
| } | |||
| deriving (Eq, Show, Ord) | |||
| data LexError | |||
| = LexError { leChar :: {-# UNPACK #-} !Char | |||
| , leLine :: {-# UNPACK #-} !Int | |||
| , leCol :: {-# UNPACK #-} !Int | |||
| } | |||
| | EOFInComment { leLine :: {-# UNPACK #-} !Int | |||
| , leCol :: {-# UNPACK #-} !Int | |||
| } | |||
| deriving (Eq, Show, Ord) | |||
| lexString :: String -> Either LexError [Token] | |||
| lexString = go 0 0 0 where | |||
| go :: Int -> Int -> Int -> String -> Either LexError [Token] | |||
| go !off !line !_ ('\n':xs) = | |||
| go (off + 1) (line + 1) 0 xs | |||
| go !off !line !col (' ':xs) = | |||
| go (off + 1) line (col + 1) xs | |||
| go !off !line !_ ('-':'-':xs) = | |||
| let (a, b) = span (/= '\n') xs | |||
| in go (off + length a) line 0 b | |||
| go !off !line !col ('{':'-':xs) = skipComment off line col 1 xs | |||
| go !off !line !col ('(':cs) = | |||
| Token line col off (off + 1) Tok_oparen `yield` go (off + 1) line (col + 1) cs | |||
| go !off !line !col (')':cs) = | |||
| Token line col off (off + 1) Tok_cparen `yield` go (off + 1) line (col + 1) cs | |||
| go !off !line !col ('{':cs) = | |||
| Token line col off (off + 1) Tok_obrace `yield` go (off + 1) line (col + 1) cs | |||
| go !off !line !col ('}':cs) = | |||
| Token line col off (off + 1) Tok_cbrace `yield` go (off + 1) line (col + 1) cs | |||
| go !off !line !col (':':cs) = | |||
| Token line col off (off + 1) Tok_colon `yield` go (off + 1) line (col + 1) cs | |||
| go !off !line !col (';':cs) = | |||
| Token line col off (off + 1) Tok_semi `yield` go (off + 1) line (col + 1) cs | |||
| go !off !line !col ('⊤':cs) = | |||
| Token line col off (off + 1) Tok_top `yield` go (off + 1) line (col + 1) cs | |||
| go !off !line !col ('≡':cs) = | |||
| Token line col off (off + 1) Tok_equiv `yield` go (off + 1) line (col + 1) cs | |||
| go !off !line !col ('=':'=':cs) = | |||
| Token line col off (off + 2) Tok_equiv `yield` go (off + 2) line (col + 2) cs | |||
| go !off !line !col ('=':cs) = | |||
| Token line col off (off + 1) Tok_equal `yield` go (off + 1) line (col + 1) cs | |||
| go !off !line !col ('→':cs) = | |||
| Token line col off (off + 1) Tok_arrow `yield` go (off + 1) line (col + 1) cs | |||
| go !off !line !col (',':cs) = | |||
| Token line col off (off + 1) Tok_comma `yield` go (off + 1) line (col + 1) cs | |||
| go !off !line !col ('_':cs) = | |||
| Token line col off (off + 1) Tok_under `yield` go (off + 1) line (col + 1) cs | |||
| go !off !line !col ('*':cs) = | |||
| Token line col off (off + 1) Tok_times `yield` go (off + 1) line (col + 1) cs | |||
| go !off !line !col ('×':cs) = | |||
| Token line col off (off + 1) Tok_times `yield` go (off + 1) line (col + 1) cs | |||
| go !off !line !col ('\\':cs) = | |||
| Token line col off (off + 1) Tok_lambda `yield` go (off + 1) line (col + 1) cs | |||
| go !off !line !col ('λ':cs) = | |||
| Token line col off (off + 1) Tok_lambda `yield` go (off + 1) line (col + 1) cs | |||
| go !off !line !col ('-':'>':cs) = | |||
| Token line col off (off + 2) Tok_arrow `yield` go (off + 2) line (col + 2) cs | |||
| go !off !line !col ('.':'1':cs) = | |||
| Token line col off (off + 2) Tok_proj1 `yield` go (off + 2) line (col + 2) cs | |||
| go !off !line !col ('.':'2':cs) = | |||
| Token line col off (off + 2) Tok_proj2 `yield` go (off + 2) line (col + 2) cs | |||
| go !off !line !col (c:cs) | |||
| | isAlpha c = goIdent off off line col (T.singleton c) cs | |||
| go !_ !line !col (c:_) = Left (LexError c line col) | |||
| go _ _ _ [] = pure [] | |||
| goIdent !soff !off !line !col !acc [] = | |||
| pure [Token line col soff off (finishIdent acc)] | |||
| goIdent !soff !off !line !col !acc (c:cs) | |||
| | isAlphaNum c || c == '\'' | |||
| = goIdent soff (off + 1) line (col + 1) (T.snoc acc c) cs | |||
| | otherwise | |||
| = Token line col soff off (finishIdent acc) `yield` go (off + 1) line (col + 1) (c:cs) | |||
| skipComment off line col level ('-':'}':cs) | |||
| | level == 1 = go off line col cs | |||
| | otherwise = skipComment off line col (level - 1) cs | |||
| skipComment off line col level ('{':'-':cs) = | |||
| skipComment off line col (level + 1) cs | |||
| skipComment _ line col _ [] = Left (EOFInComment line col) | |||
| yield c = fmap (c:) | |||
| finishIdent c | |||
| | T.pack "let" == c = Tok_let | |||
| | T.pack "Type" == c = Tok_type | |||
| | T.pack "in" == c = Tok_in | |||
| | T.pack "refl" == c = Tok_refl | |||
| | T.pack "coe" == c = Tok_coe | |||
| | T.pack "cong" == c = Tok_cong | |||
| | T.pack "sym" == c = Tok_sym | |||
| | otherwise = Tok_var c | |||
| @ -0,0 +1,219 @@ | |||
| {-# LANGUAGE TupleSections #-} | |||
| {-# LANGUAGE BlockArguments #-} | |||
| {-# LANGUAGE LambdaCase #-} | |||
| {-# LANGUAGE DerivingVia #-} | |||
| module Presyntax.Parser where | |||
| import Control.Applicative | |||
| import Control.Monad.State | |||
| import qualified Data.Text as T | |||
| import Data.Text (Text) | |||
| import Presyntax.Lexer | |||
| import Presyntax | |||
| import Syntax | |||
| data ParseError | |||
| = UnexpectedEof Int Int | |||
| | Unexpected Token | |||
| | Empty | |||
| | AltError ParseError ParseError | |||
| deriving (Show) | |||
| data ParseState | |||
| = ParseState { ptTs :: [Token] | |||
| , ptLine :: !Int | |||
| , ptCol :: !Int | |||
| } | |||
| newtype Parser a = | |||
| Parser { runParser :: ParseState -> Either ParseError (a, ParseState) } | |||
| deriving | |||
| ( Functor | |||
| , Applicative | |||
| , Monad | |||
| , MonadState ParseState | |||
| ) | |||
| via (StateT ParseState (Either ParseError)) | |||
| parseString :: Parser a -> String -> Either (Either LexError ParseError) a | |||
| parseString (Parser k) s = | |||
| case lexString s of | |||
| Left e -> Left (Left e) | |||
| Right xs -> | |||
| case k (ParseState xs 0 0) of | |||
| Left e -> Left (pure e) | |||
| Right (x, _) -> Right x | |||
| selectToken :: (Token -> Maybe a) -> Parser a | |||
| selectToken k = Parser \case | |||
| ParseState [] l c -> Left (UnexpectedEof l c) | |||
| ParseState (x:xs) _ _ -> | |||
| case k x of | |||
| Just p -> pure (p, ParseState xs (tokLine x) (tokCol x)) | |||
| Nothing -> Left (Unexpected x) | |||
| expect :: TokenClass -> Parser () | |||
| expect t = selectToken (\x -> if tokClass x == t then Just () else Nothing) | |||
| var :: Parser Text | |||
| var = selectToken \case | |||
| Token _ _ _ _ (Tok_var v) -> pure v | |||
| _ -> Nothing | |||
| optionally :: Parser a -> Parser (Maybe a) | |||
| optionally p = fmap Just p <|> pure Nothing | |||
| braces :: Parser a -> Parser a | |||
| braces k = do | |||
| expect Tok_obrace | |||
| x <- k | |||
| expect Tok_cbrace | |||
| pure x | |||
| parens :: Parser a -> Parser a | |||
| parens k = do | |||
| expect Tok_oparen | |||
| x <- k | |||
| expect Tok_cparen | |||
| pure x | |||
| instance Alternative Parser where | |||
| empty = Parser \_ -> Left Empty | |||
| Parser kx <|> Parser ky = Parser \x -> | |||
| case kx x of | |||
| Right x -> Right x | |||
| Left e -> | |||
| case ky x of | |||
| Left _ -> Left e | |||
| Right y -> Right y | |||
| attachPos :: Parser RawExpr -> Parser RawExpr | |||
| attachPos k = do | |||
| start <- gets (\(ParseState ~(x:_) _ _) -> (tokLine x, tokCol x - (tokOff x - tokSOff x))) | |||
| x <- k | |||
| end <- gets (\(ParseState _ l c) -> (l, c)) | |||
| pure (RSrcPos start end x) | |||
| body :: Parser RawExpr | |||
| body = attachPos letExpr <|> attachPos lamExpr <|> attachPos exprPi where | |||
| letExpr = do | |||
| expect Tok_let | |||
| n <- var | |||
| expect Tok_colon | |||
| t <- body | |||
| letSmol n t <|> letBig n t | |||
| letSmol n t = do | |||
| expect Tok_equal | |||
| d <- body | |||
| expect Tok_semi | |||
| Rlet n t d <$> body | |||
| letBig n t = do | |||
| expect Tok_semi | |||
| selectToken \case | |||
| Token _ _ _ _ (Tok_var n') | n' == n -> Just () | |||
| _ -> Nothing | |||
| args <- many arg | |||
| expect Tok_equal | |||
| d <- body | |||
| expect Tok_semi | |||
| Rlet n t (foldr lam d args) <$> body | |||
| lamExpr = do | |||
| expect Tok_lambda | |||
| vs <- some arg | |||
| expect Tok_arrow | |||
| e <- body | |||
| pure (foldr lam e vs) | |||
| arg = fmap (Ex,) var <|> fmap (Im,) (braces var) | |||
| lam (p, v) b = Rlam p v b | |||
| exprPi :: Parser RawExpr | |||
| exprPi = attachPos $ | |||
| do | |||
| bs <- optionally binder | |||
| case bs of | |||
| Just k -> foldl (.) id k <$> attachPos exprPi | |||
| Nothing -> attachPos exprArr | |||
| where | |||
| binder = (some (parens (bind Ex) <|> braces (bind Im)) <* expect Tok_arrow) | |||
| <|> (fmap pure (parens sigma) <* expect Tok_times) | |||
| bind p = do | |||
| names <- some var | |||
| expect Tok_colon | |||
| t <- exprPi | |||
| pure (foldr (\n k -> Rpi p n t . k) id names) | |||
| sigma = do | |||
| n <- var | |||
| expect Tok_colon | |||
| Rsigma n <$> exprPi | |||
| exprArr :: Parser RawExpr | |||
| exprArr = attachPos $ do | |||
| t <- attachPos exprApp | |||
| c <- optionally (fmap (const True) (expect Tok_arrow) <|> fmap (const False) (expect Tok_times)) | |||
| case c of | |||
| Just True -> Rpi Ex (T.singleton '_') t <$> exprPi | |||
| Just False -> Rsigma (T.singleton '_') t <$> exprPi | |||
| Nothing -> pure t | |||
| exprEq0 :: Parser RawExpr | |||
| exprEq0 = attachPos $ | |||
| do | |||
| head <- atom | |||
| spine <- many spineEntry | |||
| pure (foldl app head spine) | |||
| where | |||
| spineEntry = fmap (Ex,) atom <|> fmap (Im,) (braces exprPi) | |||
| app f (x, s) = Rapp x f s | |||
| exprApp :: Parser RawExpr | |||
| exprApp = attachPos $ do | |||
| t <- exprEq0 | |||
| c <- optionally (expect Tok_equiv) | |||
| case c of | |||
| Just () -> Req t <$> exprEq0 | |||
| Nothing -> pure t | |||
| atom0 :: Parser RawExpr | |||
| atom0 = attachPos $ | |||
| fmap Rvar var | |||
| <|> fmap (const Rtype) (expect Tok_type) | |||
| <|> fmap (const Rhole) (expect Tok_under) | |||
| <|> fmap (const Rtop) (expect Tok_top) | |||
| <|> fmap (const Rrefl) (expect Tok_refl) | |||
| <|> fmap (const Rcoe) (expect Tok_coe) | |||
| <|> fmap (const Rcong) (expect Tok_cong) | |||
| <|> fmap (const Rsym) (expect Tok_sym) | |||
| <|> fmap (const Runit) (parens (pure ())) | |||
| <|> parens pair | |||
| pair :: Parser RawExpr | |||
| pair = attachPos $ do | |||
| t <- body | |||
| c <- optionally (expect Tok_comma) | |||
| case c of | |||
| Just () -> Rpair t <$> pair | |||
| Nothing -> pure t | |||
| atom :: Parser RawExpr | |||
| atom = attachPos $ | |||
| do | |||
| e <- atom0 | |||
| c <- many (selectToken (projection . tokClass)) | |||
| pure $ case c of | |||
| [] -> e | |||
| sls -> foldl (flip ($)) e sls | |||
| where | |||
| projection Tok_proj1 = pure Rproj1 | |||
| projection Tok_proj2 = pure Rproj2 | |||
| projection _ = Nothing | |||
| @ -0,0 +1,62 @@ | |||
| {-# LANGUAGE DeriveDataTypeable #-} | |||
| {-# LANGUAGE GeneralizedNewtypeDeriving #-} | |||
| {-# LANGUAGE PatternSynonyms #-} | |||
| module Syntax where | |||
| import Data.Text (Text) | |||
| import Data.Data (Data, Typeable) | |||
| data Plicity | |||
| = Im | |||
| | Ex | |||
| deriving (Eq, Show, Ord, Data, Typeable) | |||
| newtype Var = Bound Int | |||
| deriving (Eq, Show, Ord, Data, Typeable) | |||
| data BoundDef = BDBound Text | BDDefined Text | |||
| deriving (Eq, Show, Ord, Data, Typeable) | |||
| newtype MetaVar = MV { getMV :: Int } | |||
| deriving (Eq, Show, Ord, Data, Typeable) | |||
| data Term | |||
| = Var Var | |||
| | Con Text | |||
| | Let Text Term Term Term | |||
| | Type | Prop | |||
| | Pi Plicity Text Term Term | |||
| | Lam Plicity Text Term | |||
| | App Plicity Term Term | |||
| | Sigma Text Term Term | |||
| | Pair Term Term | |||
| | Proj1 Term | |||
| | Proj2 Term | |||
| | Meta MetaVar | |||
| | NewMeta MetaVar [BoundDef] | |||
| | Id Term Term Term | |||
| | Refl | |||
| | Coe | |||
| | Cong | |||
| | Sym | |||
| | Top | Unit | |||
| deriving (Eq, Show, Ord, Typeable, Data) | |||
| pattern Bv :: Int -> Term | |||
| pattern Bv i = Var (Bound i) | |||
| data Telescope | |||
| = End | |||
| | Ext Telescope Text Term | |||
| deriving (Eq, Show, Ord) | |||
| newtype Level = Lvl {unLvl :: Int} | |||
| deriving (Eq, Show, Ord, Enum) | |||
| lvl2Ix :: Level -> Level -> Int | |||
| lvl2Ix (Lvl l) (Lvl x) = l - x - 1 | |||
| @ -0,0 +1,135 @@ | |||
| {-# LANGUAGE ViewPatterns #-} | |||
| module Syntax.Pretty where | |||
| import Syntax | |||
| import Data.Text ( Text ) | |||
| import qualified Data.Text as T | |||
| import Elaboration.Monad | |||
| type Prec = Int | |||
| domainPrec, funcPrec, argPrec :: Int | |||
| domainPrec = 3 | |||
| argPrec = 2 | |||
| funcPrec = 1 | |||
| showWithPrec :: [Text] -> Int -> Term -> ShowS | |||
| showWithPrec names p (App Ex x y) = | |||
| showParen (p >= argPrec) $ | |||
| showWithPrec names funcPrec x | |||
| . showChar ' ' | |||
| . showWithPrec names argPrec y | |||
| showWithPrec names p (App Im x _) = showWithPrec names p x | |||
| showWithPrec _ _ Type = showString "Type" | |||
| showWithPrec _ _ Top = showString "⊤" | |||
| showWithPrec _ _ Unit = showString "()" | |||
| -- Reflexivity | |||
| showWithPrec _ _ Refl = showString "refl" | |||
| -- Casting | |||
| showWithPrec _ _ Coe = showString "coe" | |||
| -- Congruence (x == y → f x == f y) | |||
| showWithPrec _ _ Cong = showString "cong" | |||
| -- Symmetry | |||
| showWithPrec _ _ Sym = showString "sym" | |||
| showWithPrec _ _ (Meta (MV i)) = showChar '?' . shows i | |||
| showWithPrec _ _ (NewMeta (MV i) _) = showChar '?' . shows i | |||
| showWithPrec names _ (Bv i) = | |||
| if i < 0 | |||
| then showString "α" | |||
| else showString (T.unpack (names !! i)) | |||
| showWithPrec names _ (Proj1 x) = showWithPrec names funcPrec x . showString ".1" | |||
| showWithPrec names _ (Proj2 x) = showWithPrec names funcPrec x . showString ".2" | |||
| showWithPrec names p (Lam i t e) = | |||
| showParen (p >= funcPrec) $ | |||
| showChar 'λ' | |||
| . showsPlicity i id (showString (T.unpack t)) | |||
| . showString " → " | |||
| . showWithPrec (t:names) 0 e | |||
| showWithPrec names p (Pi Ex (T.unpack -> "_") d r) = | |||
| showParen (p >= argPrec) $ | |||
| showWithPrec names domainPrec d | |||
| . showString " -> " | |||
| . showWithPrec (T.singleton '_':names) 0 r | |||
| showWithPrec names p (Pi i n d r) = | |||
| showParen (p >= argPrec) $ | |||
| showsPlicity i (showParen True) | |||
| ( showString (T.unpack n) | |||
| . showString " : " | |||
| . showWithPrec names 0 d | |||
| ) | |||
| . showString " -> " | |||
| . showWithPrec (n:names) 0 r | |||
| showWithPrec names p (Sigma (T.unpack -> "_") d r) = | |||
| showParen (p >= argPrec) $ | |||
| showWithPrec names domainPrec d | |||
| . showString " × " | |||
| . showWithPrec (T.singleton '_':names) 0 r | |||
| showWithPrec names p (Sigma n d r) = | |||
| showParen (p >= argPrec) $ | |||
| showParen True | |||
| ( showString (T.unpack n) | |||
| . showString " : " | |||
| . showWithPrec names 0 d | |||
| ) | |||
| . showString " × " | |||
| . showWithPrec (n:names) 0 r | |||
| showWithPrec names _ (Pair a b) = | |||
| showParen True $ | |||
| showWithPrec names 0 a | |||
| . showString " , " | |||
| . showWithPrec names 0 b | |||
| showWithPrec names p (Id _ b c) = | |||
| showParen (p >= funcPrec) $ | |||
| showWithPrec names argPrec b . showString " == " . showWithPrec names argPrec c | |||
| showWithPrec names p (Let x t d e) = | |||
| showParen (p >= funcPrec) $ | |||
| showString "let\n" | |||
| . showString (" " ++ T.unpack x) | |||
| . showString " : " | |||
| . showWithPrec names 0 t | |||
| . showChar '\n' | |||
| . showString (" " ++ T.unpack x ++ " = ") | |||
| . showWithPrec names 0 d | |||
| . showString ";\n" | |||
| . showWithPrec (x:names) 0 e | |||
| showTerm :: Int -> Term -> ShowS | |||
| showTerm = showWithPrec (iterate (`T.snoc` '\'') (T.pack "x")) | |||
| showsPlicity :: Plicity -> (ShowS -> ShowS) -> ShowS -> ShowS | |||
| showsPlicity Ex f k = f k | |||
| showsPlicity Im _ k = showChar '{' . k . showChar '}' | |||
| showElabError :: ElabError -> ShowS | |||
| showElabError (NotInScope t) = showString "Variable not in scope: " . shows t | |||
| showElabError (NotFunction names t) = | |||
| showString "Type is not a function type: " | |||
| . showWithPrec (names ++ exes) 0 t | |||
| where | |||
| exes = iterate (`T.snoc` '\'') (T.pack "x") | |||
| showElabError (NotEqual names a b) = | |||
| showString "Types are not equal:" | |||
| . showString "\n * " . showWithPrec (names ++ exes) 0 a | |||
| . showString "\n vs" | |||
| . showString "\n * " . showWithPrec (names ++ exes) 0 b | |||
| where | |||
| exes = iterate (`T.snoc` '\'') (T.pack "x") | |||
| showElabError (CantSolveMeta ns q t) = | |||
| showString "Equation has no (unique) solution: " | |||
| . showString "\n " . showWithPrec (ns ++ exes) 0 q | |||
| . showString " ≡? " . showWithPrec (ns ++ exes) 0 t | |||
| where | |||
| exes = iterate (`T.snoc` '\'') (T.pack "x") | |||
| @ -0,0 +1,124 @@ | |||
| {-# LANGUAGE ViewPatterns #-} | |||
| {-# LANGUAGE DeriveDataTypeable #-} | |||
| {-# LANGUAGE StrictData, PatternSynonyms #-} | |||
| module Value where | |||
| import Data.Sequence (Seq) | |||
| import Data.Text (Text) | |||
| import Syntax | |||
| import Data.Data | |||
| import qualified Data.Sequence as Seq | |||
| newtype Env = | |||
| Env { locals :: Seq Value } | |||
| deriving (Eq, Show, Ord, Data, Typeable) | |||
| emptyEnv :: Env | |||
| emptyEnv = Env mempty | |||
| type VTy = Value | |||
| data Closure | |||
| = Closure !Env !Term | |||
| | ClMeta MetaFun | |||
| deriving (Eq, Ord, Data, Typeable) | |||
| instance Show Closure where | |||
| showsPrec x (Closure _ t) = showsPrec x t | |||
| showsPrec x (ClMeta f) = showsPrec x f | |||
| newtype MetaFun = MetaFun { runMC :: Value -> Value } | |||
| instance Eq MetaFun where | |||
| _ == _ = False | |||
| instance Ord MetaFun where | |||
| _ <= _ = True | |||
| instance Show MetaFun where | |||
| show _ = "«meta»" | |||
| instance Data MetaFun where | |||
| gunfold _ _ _ = error "gunfold MetaFun" | |||
| toConstr _ = error "gunfold MetaFun" | |||
| dataTypeOf _ = mkNoRepType "MetaFun" | |||
| data Value | |||
| -- Universes | |||
| = VType | |||
| -- Canonical Π-types and λ values | |||
| | VPi Plicity Text ~Value {-# UNPACK #-} Closure | |||
| | VLam Plicity Text {-# UNPACK #-} Closure | |||
| -- Variable applied to some values, with a | |||
| -- suspended evaluated result that might | |||
| -- be forced later | |||
| | VGlued Head (Seq SpineThing) ~(Maybe Value) | |||
| -- Canonical Σ-types and pair values | |||
| | VSigma Text ~Value {-# UNPACK #-} Closure | |||
| | VPair Value Value | |||
| -- Id A a b | |||
| | VEq Value Value Value | |||
| -- Id A a b ≡ t | |||
| | VEqG Value Value Value Value | |||
| | VTop | VUnit | |||
| deriving (Eq, Show, Ord, Data, Typeable) | |||
| data SpineThing | |||
| = AppEx Value | |||
| | AppIm Value | |||
| | SProj1 | |||
| | SProj2 | |||
| deriving (Eq, Show, Ord, Data, Typeable) | |||
| flexible :: Value -> Bool | |||
| flexible VGlued{} = True | |||
| flexible VEqG{} = True | |||
| flexible _ = False | |||
| pattern VNe :: Head -> Seq SpineThing -> Value | |||
| pattern VNe x y = VGlued x y Nothing | |||
| pattern VProj1 :: Value -> Value | |||
| pattern VProj1 t <- (matchP1 -> Just t) where | |||
| VProj1 t = | |||
| case t of | |||
| VGlued h s n -> VGlued h (s Seq.:|> SProj1) n | |||
| matchP1 :: Value -> Maybe Value | |||
| matchP1 (VPair x _) = Just x | |||
| matchP1 (VGlued h (s Seq.:|> SProj1) n) = Just (VGlued h s n) | |||
| matchP1 _ = Nothing | |||
| pattern VProj2 :: Value -> Value | |||
| pattern VProj2 t <- (matchP2 -> Just t) where | |||
| VProj2 t = | |||
| case t of | |||
| VGlued h s n -> VGlued h (s Seq.:|> SProj2) n | |||
| matchP2 :: Value -> Maybe Value | |||
| matchP2 (VPair _ x) = Just x | |||
| matchP2 (VGlued h (s Seq.:|> SProj2) n) = Just (VGlued h s n) | |||
| matchP2 _ = Nothing | |||
| data Meta | |||
| = Unsolved [Text] Value | |||
| | Solved Value | |||
| deriving (Eq, Show) | |||
| vVar :: Var -> Value | |||
| vVar x = VGlued (HVar x) mempty Nothing | |||
| data Head | |||
| = HVar Var | |||
| | HCon Text | |||
| | HMeta MetaVar | |||
| | HRefl | |||
| | HCoe | |||
| | HCong | |||
| | HSym | |||
| deriving (Eq, Show, Ord, Data, Typeable) | |||
| @ -0,0 +1,66 @@ | |||
| # This file was automatically generated by 'stack init' | |||
| # | |||
| # Some commonly used options have been documented as comments in this file. | |||
| # For advanced use and comprehensive documentation of the format, please see: | |||
| # https://docs.haskellstack.org/en/stable/yaml_configuration/ | |||
| # Resolver to choose a 'specific' stackage snapshot or a compiler version. | |||
| # A snapshot resolver dictates the compiler version and the set of packages | |||
| # to be used for project dependencies. For example: | |||
| # | |||
| # resolver: lts-3.5 | |||
| # resolver: nightly-2015-09-21 | |||
| # resolver: ghc-7.10.2 | |||
| # | |||
| # The location of a snapshot can be provided as a file or url. Stack assumes | |||
| # a snapshot provided as a file might change, whereas a url resource does not. | |||
| # | |||
| # resolver: ./custom-snapshot.yaml | |||
| # resolver: https://example.com/snapshots/2018-01-01.yaml | |||
| resolver: lts-16.20 | |||
| # User packages to be built. | |||
| # Various formats can be used as shown in the example below. | |||
| # | |||
| # packages: | |||
| # - some-directory | |||
| # - https://example.com/foo/bar/baz-0.0.2.tar.gz | |||
| # subdirs: | |||
| # - auto-update | |||
| # - wai | |||
| packages: | |||
| - . | |||
| # Dependency packages to be pulled from upstream that are not in the resolver. | |||
| # These entries can reference officially published versions as well as | |||
| # forks / in-progress versions pinned to a git hash. For example: | |||
| # | |||
| # extra-deps: | |||
| # - acme-missiles-0.3 | |||
| # - git: https://github.com/commercialhaskell/stack.git | |||
| # commit: e7b331f14bcffb8367cd58fbfc8b40ec7642100a | |||
| # | |||
| # extra-deps: [] | |||
| # Override default flag values for local packages and extra-deps | |||
| # flags: {} | |||
| # Extra package databases containing global packages | |||
| # extra-package-dbs: [] | |||
| # Control whether we use the GHC we find on the path | |||
| # system-ghc: true | |||
| # | |||
| # Require a specific version of stack, using version ranges | |||
| # require-stack-version: -any # Default | |||
| # require-stack-version: ">=2.4" | |||
| # | |||
| # Override the architecture used by stack, especially useful on Windows | |||
| # arch: i386 | |||
| # arch: x86_64 | |||
| # | |||
| # Extra directories used by stack for building | |||
| # extra-include-dirs: [/path/to/dir] | |||
| # extra-lib-dirs: [/path/to/dir] | |||
| # | |||
| # Allow a newer minor version of GHC than the snapshot specifies | |||
| # compiler-check: newer-minor | |||
| @ -0,0 +1,12 @@ | |||
| # This file was autogenerated by Stack. | |||
| # You should not edit this file by hand. | |||
| # For more information, please see the documentation at: | |||
| # https://docs.haskellstack.org/en/stable/lock_files | |||
| packages: [] | |||
| snapshots: | |||
| - completed: | |||
| size: 532177 | |||
| url: https://raw.githubusercontent.com/commercialhaskell/stackage-snapshots/master/lts/16/20.yaml | |||
| sha256: 0e14ba5603f01e8496e8984fd84b545a012ca723f51a098c6c9d3694e404dc6d | |||
| original: lts-16.20 | |||
| @ -0,0 +1,137 @@ | |||
| -- Equality with an explicit domain | |||
| let | |||
| Eq : (A : Type) (x y : A) -> Type; | |||
| Eq A x y = x == y; | |||
| -- Identity function with an explicit domain | |||
| -- (works as a type annotation) | |||
| let | |||
| the : (A : Type) -> A -> A; | |||
| the A x = x; | |||
| -- Singleton types | |||
| -- The subtype of A generated by "being equal to x : A" | |||
| let | |||
| singl : (A : Type) (x : A) -> Type; | |||
| singl A x = (y : A) * x == y; | |||
| -- Singletons are contractible | |||
| let | |||
| singlC : {A : Type} {a b : A} (p : a == b) -> Eq (singl A a) (a, refl) (b, p); | |||
| singlC p = (p, ()); | |||
| -- Substitution follows from transport + congruence | |||
| -- (just transport by the congruence under P) | |||
| let | |||
| subst : {A : Type} (P : A -> Type) {x y : A} (p : x == y) -> P x -> P y; | |||
| subst P path px = coe (cong P path) px; | |||
| let | |||
| coe2 : {A B : Type} (p : A == B) → A → B; | |||
| coe2 p = subst (λ x → x) p; | |||
| -- Based path induction follows from contractibility of singletons + | |||
| -- substitution | |||
| let | |||
| J : {A : Type} (a : A) (P : (b : A) -> a == b -> Type) | |||
| (d : P a refl) (b : A) (p : a == b) -> P b p; | |||
| J {A} a P d b p = | |||
| subst {singl A a} (λ y → P y.1 y.2) (singlC p) d; | |||
| let | |||
| JComp : {A : Type} (a : A) (P : (b : A) -> a == b -> Type) | |||
| (d : P a refl) | |||
| → J {A} a P d a refl == d; | |||
| JComp {A} a P d = refl; | |||
| -- Symmetry follows from axiom J | |||
| let | |||
| symm : {A : Type} {x y : A} (p : x == y) -> y == x; | |||
| symm {A} {x} {y} p = J x (λ y p -> y == x) refl y p; | |||
| let | |||
| symIsRefl : {A : Type} {a : A} → symm (refl {A} {a}) == refl {A} {a}; | |||
| symIsRefl = refl; | |||
| let | |||
| isContr : Type -> Type; | |||
| isContr A = (x : A) * (y : A) -> y == x; | |||
| let | |||
| comp : {A : Type} {a b c : A} → a == b → b == c → a == c; | |||
| comp {A} {a} p q = subst (λ x → a == x) q (subst (λ x → a == x) p (refl {A} {a})); | |||
| let | |||
| trans : {A : Type} {a b c : A} → b == c → a == b → a == c; | |||
| trans {A} {a} p q = comp q p; | |||
| let | |||
| transSym : {A : Type} {a : A} → (p : a == a) → comp p (symm p) == refl; | |||
| transSym p = refl; | |||
| let | |||
| existsOne : (A : Type) (B : A -> Type) -> ((x : A) × B x) -> isContr A -> (x : A) -> B x; | |||
| existsOne A B prf contr it = | |||
| subst B (comp (contr.2 prf.1) (sym (contr.2 it))) prf.2; | |||
| let | |||
| indOne : (P : ⊤ -> Type) -> P () -> (x : ⊤) -> P x; | |||
| indOne P p x = subst P () p; | |||
| let | |||
| false : Type; | |||
| false = (A : Type) → A; | |||
| let | |||
| exFalso : (P : Type) -> false -> P; | |||
| exFalso P f = f P; | |||
| let | |||
| funExt : {A : Type} {B : A -> Type} {f g : (x : A) -> B x} | |||
| -> ((x : A) -> f x == g x) -> f == g; | |||
| funExt p = p; | |||
| let | |||
| hfunext : {A : Type} {B : A -> Type} {f g : (x : A) -> B x} | |||
| -> ((x : A) -> f x == g x) == (f == g); | |||
| hfunext = refl; | |||
| let | |||
| allAbsurd : {A : Type} (f g : false -> A) -> f == g; | |||
| allAbsurd f g x = exFalso (f x == g x) x; | |||
| let | |||
| coerceR1 : {A : Type} | |||
| → Eq (A == A → A → A) | |||
| (λ p x → coe {A} {A} p x) | |||
| (λ x y → y); | |||
| coerceR1 = refl; | |||
| let | |||
| K : {A : Type} {x : A} (P : x == x → Type) | |||
| → P refl → (p : x == x) → P p; | |||
| K P p path = subst P (the (refl == path) ()) p; | |||
| let | |||
| foo : {A : Type} {B : A -> Type} {f : (x : A) -> B x} | |||
| -> Eq (f == f) refl (λ x → refl); | |||
| foo = K (λ e → (refl {_} {f}) == e) refl (λ x → refl); | |||
| let | |||
| coh : {A : Type} (p : A == A) (x : A) → coe p == (λ x → x); | |||
| coh path elem x = refl; | |||
| let | |||
| coh2 : {A : Type} (p : A == A) (x : A) → coe p x == x; | |||
| coh2 path elem = K (λ path → coe {A} {A} path elem == elem) refl path; | |||
| -- let | |||
| -- cohsAgree : {A : Type} (p : A == A) (x : A) → coh {A} p x == coh2 {A} p x; | |||
| -- cohsAgree path elem = refl; | |||
| let | |||
| congComp : {A B : Type} (f : A -> B) {x : A} | |||
| -> cong f (refl {A} {x}) == refl {B} {f x}; | |||
| congComp f = refl; | |||
| coe | |||
| @ -0,0 +1,25 @@ | |||
| let | |||
| congComp : {A B C : Type} (f : A -> B) (g : B -> C) {x y : A} (p : x == y) | |||
| -> cong (λ a → g (f a)) p == cong g (cong f p); | |||
| congComp f g p = refl; | |||
| let | |||
| the : (A : Type) -> A -> A; | |||
| the A x = x; | |||
| let | |||
| congId : {A : Type} {x y : A} (p : x == y) | |||
| -> cong (λ x → x) p == p; | |||
| congId p = (); | |||
| let | |||
| axUIP : {A : Type} {x y : A} (p q : x == y) | |||
| -> p == q; | |||
| axUIP p q = (); | |||
| let | |||
| symSym : {A : Type} {x y : A} (p : x == y) | |||
| -> sym (sym p) == p; | |||
| symSym p = refl; | |||
| congComp | |||
| @ -0,0 +1,6 @@ | |||
| let | |||
| congComp : {A B : Type} (f : A -> B) {x : A} | |||
| -> cong f (refl {A} {x}) == refl {B} {f x}; | |||
| congComp f = refl; | |||
| congComp | |||