@ -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 |