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