@ -0,0 +1 @@ | |||
.stack-work |
@ -0,0 +1,30 @@ | |||
Copyright Abigail Magalhães (c) 2021 | |||
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 @@ | |||
# indexed |
@ -0,0 +1,2 @@ | |||
import Distribution.Simple | |||
main = defaultMain |
@ -0,0 +1,2 @@ | |||
cradle: | |||
stack: |
@ -0,0 +1,34 @@ | |||
name: indexed | |||
version: 0.1.0.0 | |||
-- synopsis: | |||
-- description: | |||
homepage: https://github.com/plt-hokusai/indexed#readme | |||
license: BSD3 | |||
license-file: LICENSE | |||
author: Abigail Magalhães | |||
maintainer: [email protected] | |||
copyright: 2021 Abigail Magalhães | |||
category: Web | |||
build-type: Simple | |||
cabal-version: >=1.10 | |||
extra-source-files: README.md | |||
executable indexed | |||
hs-source-dirs: src | |||
main-is: Main.hs | |||
default-language: Haskell2010 | |||
build-depends: base >= 4.7 && < 5 | |||
, mtl | |||
, text | |||
, haskeline | |||
, exceptions | |||
, containers | |||
, megaparsec | |||
other-modules: Syntax | |||
, Eval | |||
, Elab | |||
, Systems | |||
, Presyntax | |||
, Presyntax.Parser | |||
, Presyntax.Lexer |
@ -0,0 +1,288 @@ | |||
{-# LANGUAGE ViewPatterns #-} | |||
{-# LANGUAGE LambdaCase #-} | |||
{-# LANGUAGE BlockArguments #-} | |||
{-# LANGUAGE TupleSections #-} | |||
{-# LANGUAGE DeriveAnyClass #-} | |||
module Elab where | |||
import Control.Exception | |||
import qualified Data.Map.Strict as Map | |||
import Data.Typeable | |||
import qualified Presyntax as P | |||
import Syntax | |||
import Eval | |||
import Control.Monad | |||
import Systems | |||
import Data.Traversable | |||
import qualified Data.Set as Set | |||
import Data.Set (Set) | |||
import Data.Foldable | |||
data TypeError | |||
= NotInScope String | |||
| UnifyError UnifyError | |||
| WrongFaces Value [([Value], Value, Elab.TypeError)] | |||
| InSpan (Int, Int) (Int, Int) Elab.TypeError | |||
| IncompleteSystem P.Formula P.Formula | |||
| IncompatibleFaces (P.Formula, Term) (P.Formula, Term) Elab.TypeError | |||
| InvalidSystem (Set Face) (Set Face) | |||
deriving (Show, Typeable, Exception) | |||
check :: Env -> P.Exp -> Value -> IO Term | |||
check env (P.Span s e exp) wants = | |||
check env exp wants | |||
`catch` \case | |||
InSpan s e err -> throwIO $ InSpan s e err | |||
err -> throwIO $ InSpan s e err | |||
check env exp (VSub a fm@(toFormula -> Just phi) el) = do | |||
tm <- check env exp a | |||
for (addFormula phi env) \env -> | |||
let tm' = eval env tm | |||
in unifyTC env tm' el | |||
pure (InclSub (quote a) (quote fm) (quote el) tm) | |||
check env (P.Lam s b) expected = do | |||
expc <- isPiOrPathType expected | |||
case expc of | |||
Left (_, d, r) -> do -- function | |||
bd <- check env { names = Map.insert s (makeValueGluingSub d s) (names env) } b (r (VVar s)) | |||
pure (Lam s (quote d) bd) | |||
Right (a, x, y) -> do | |||
bd <- check env { names = Map.insert s (VI, VVar s) (names env) } b (a @@ VVar s) | |||
let t = Lam s I bd | |||
t' = eval env t | |||
checkBoundary env [s] t' | |||
[ ([VI0], x) | |||
, ([VI1], y) | |||
] | |||
pure (PathI (quote a) (quote x) (quote y) s bd) | |||
check env (P.Let v t d b) expected = do | |||
ty <- check env t VType | |||
let ty' = eval env ty | |||
d <- check env d ty' | |||
let d' = eval env d | |||
b <- check env { names = Map.insert v (ty', d') (names env) } b expected | |||
pure (Let v (quote ty') d b) | |||
check env (P.Pair a b) expected = do | |||
(_, fst, snd) <- isSigmaType expected | |||
a <- check env a fst | |||
let a' = eval env a | |||
b <- check env b (snd a') | |||
pure (Pair a b) | |||
check env (P.Partial fs) ty = do | |||
let formula = orFormula (map fst fs) | |||
(extent, ty) <- isPartialType formula ty | |||
let ourFaces = Systems.faces formula | |||
extentFaces = Systems.faces extent | |||
unless (formula == extent) $ | |||
throwIO $ IncompleteSystem formula extent | |||
let range = formulaToTm $ toDNF formula | |||
rangeTm <- check env range VI | |||
let rangeTy = eval env rangeTm | |||
ts <- for fs $ \(fn, tn) -> do | |||
tms <- for (addFormula fn env) \env -> check env tn ty | |||
pure (fn, head tms) | |||
fmap (System . FMap . Map.fromList) $ for ts \(fn, tn) -> do | |||
for ts \(fm, tm) -> do | |||
when (possible (fn `P.And` fm)) do | |||
for_ (addFormula (fn `P.And` fm) env) $ \env -> | |||
unifyTC (env) (eval env tn) (eval env tm) | |||
`catch` \e -> throwIO (IncompatibleFaces (fn, tn) (fm, tm) e) | |||
pure (fn, tn) | |||
check env exp expected = do | |||
(term, actual) <- infer env exp | |||
unifyTC env actual expected | |||
pure term | |||
makeValueGluingSub :: Value -> String -> (Value, Value) | |||
makeValueGluingSub ty@(VSub a phi a0) s = (ty, VOfSub a phi a0 (VVar s)) | |||
makeValueGluingSub ty s = (ty, VVar s) | |||
addFormula :: P.Formula -> Env -> [Env] | |||
addFormula (P.And x y) = addFormula x >=> addFormula y | |||
addFormula (P.Or x y) = (++) <$> addFormula x <*> addFormula y | |||
addFormula P.Top = pure | |||
addFormula P.Bot = const [] | |||
addFormula (P.Is0 x) = \env -> pure env{ names = Map.insert x (VI, VI0) (names env) } | |||
addFormula (P.Is1 x) = \env -> pure env{ names = Map.insert x (VI, VI1) (names env) } | |||
unifyTC :: Env -> Value -> Value -> IO () | |||
unifyTC env a b = unify env a b `catch` \e -> const (throwIO (UnifyError (Mismatch a b))) (e :: UnifyError) | |||
checkBoundary :: Env -> [String] -> Value -> [([Value], Value)] -> IO () | |||
checkBoundary env ns f = finish <=< go where | |||
go :: [([Value], Value)] -> IO [([Value], Value, Elab.TypeError)] | |||
go [] = pure [] | |||
go ((ixs, vl):faces) = do | |||
let env' = foldr (\(x, t) env -> env { names = Map.insert x t (names env) }) env (zip ns (zip (repeat VI) ixs)) | |||
t <- try $ unifyTC env' (foldl (@@) f ixs) vl | |||
case t of | |||
Right _ -> go faces | |||
Left e -> ((ixs, vl, e):) <$> go faces | |||
finish [] = pure () | |||
finish xs = throwIO $ WrongFaces f xs | |||
infer :: Env -> P.Exp -> IO (Term, Value) | |||
infer env (P.Span s e exp) = | |||
infer env exp | |||
`catch` \case | |||
InSpan s e err -> throwIO $ InSpan s e err | |||
err -> throwIO $ InSpan s e err | |||
infer env (P.Var s) = | |||
case Map.lookup s (names env) of | |||
Just (t, _) -> pure (Var s, t) | |||
Nothing -> throwIO (NotInScope s) | |||
infer env (P.App f x) = do | |||
(fun, ty) <- infer env f | |||
funt <- isPiOrPathType ty | |||
case funt of | |||
Left (_, dom, rng) -> do | |||
arg <- check env x dom | |||
let arg' = eval env arg | |||
pure (App fun arg, rng arg') | |||
Right (a, ai0, ai1) -> do | |||
arg <- check env x VI | |||
let arg' = eval env arg | |||
pure (PathP (quote a) (quote ai0) (quote ai1) fun arg, a @@ arg') | |||
infer env (P.Pi s d r) = do | |||
dom <- check env d VType | |||
let d' = eval env dom | |||
rng <- check env { names = Map.insert s (d', VVar s) (names env) } r VType | |||
pure (Pi s dom rng, VType) | |||
infer env (P.Sigma s d r) = do | |||
dom <- check env d VType | |||
let d' = eval env dom | |||
rng <- check env { names = Map.insert s (d', VVar s) (names env) } r VType | |||
pure (Sigma s dom rng, VType) | |||
infer env P.Type = pure (Type, VType) | |||
infer env P.I = pure (I, VType) | |||
infer env P.I0 = pure (I0, VI) | |||
infer env P.I1 = pure (I1, VI) | |||
infer env (P.Cut e t) = do | |||
t <- check env t VType | |||
let t' = eval env t | |||
(, t') <$> check env e t' | |||
infer env (P.IAnd x y) = do | |||
x <- check env x VI | |||
y <- check env y VI | |||
pure (IAnd x y, VI) | |||
infer env (P.IOr x y) = do | |||
x <- check env x VI | |||
y <- check env y VI | |||
pure (IOr x y, VI) | |||
infer env P.Path = do | |||
pure | |||
( Lam "A" (quote index_t) $ | |||
Lam "x" (App (Var "A") I0) $ | |||
Lam "y" (App (Var "A") I1) $ | |||
Path (Var "A") (Var "x") (Var "y") | |||
, VPi "A" index_t \a -> | |||
VPi "x" (a @@ VI0) \_ -> | |||
VPi "y" (a @@ VI1) (const VType)) | |||
infer env P.PartialT = do | |||
pure | |||
( Lam "r" I $ | |||
Lam "A" Type $ | |||
Partial (Var "r") (Var "A") | |||
, VPi "I" VI \i -> | |||
VPi "A" VType (const VType)) | |||
infer env P.Comp = do | |||
let u_t a r = VPi "i" VI \i -> VPartial r (a @@ i) | |||
pure | |||
( Lam "A" (quote index_t) $ | |||
Lam "phi" I $ | |||
Lam "u" (quote (u_t (VVar "A") (VVar "r"))) $ | |||
Lam "a0" (Sub (App (Var "A") I0) (Var "phi") (App (Var "u") I0)) $ | |||
Comp (Var "A") (Var "phi") (Var "u") (Var "a0") | |||
, VPi "A" index_t \a -> | |||
VPi "phi" VI \phi -> | |||
VPi "u" (u_t a phi) \u -> | |||
VPi "_" (VSub (a @@ VI0) phi (u @@ VI0)) \_ -> | |||
a @@ VI1 | |||
) | |||
infer env P.SubT = do | |||
pure | |||
( Lam "A" Type $ | |||
Lam "phi" I $ | |||
Lam "u" (Partial (Var "phi") (Var "A")) $ | |||
Sub (Var "A") (Var "phi") (Var "u") | |||
, VPi "A" VType \a -> | |||
VPi "phi" VI \phi -> | |||
VPi "_" (VPartial phi a) (const VType) | |||
) | |||
infer env (P.INot x) = (, VI) . INot <$> check env x VI | |||
infer env P.Lam{} = error "can't infer type for lambda" | |||
infer env (P.Let v t d b) = do | |||
ty <- check env t VType | |||
let ty' = eval env ty | |||
d <- check env d ty' | |||
let d' = eval env d | |||
(b, t) <- infer env{ names = Map.insert v (ty', d') (names env) } b | |||
pure (Let v ty d b, t) | |||
infer env (P.Proj1 x) = do | |||
(t, ty) <- infer env x | |||
(_, d, _) <- isSigmaType ty | |||
pure (Proj1 t, d) | |||
infer env (P.Proj2 x) = do | |||
(t, ty) <- infer env x | |||
let t' = eval env t | |||
(_, _, r) <- isSigmaType ty | |||
pure (Proj2 t, r (proj1 t')) | |||
formulaToTm :: P.Formula -> P.Exp | |||
formulaToTm (P.Is0 i) = P.INot (P.Var i) | |||
formulaToTm (P.Is1 i) = P.Var i | |||
formulaToTm (P.And x y) = P.IAnd (formulaToTm x) (formulaToTm y) | |||
formulaToTm (P.Or x y) = P.IOr (formulaToTm x) (formulaToTm y) | |||
formulaToTm P.Top = P.I1 | |||
formulaToTm P.Bot = P.I0 | |||
checkFormula :: Env -> P.Formula -> IO () | |||
checkFormula env P.Top = pure () | |||
checkFormula env P.Bot = pure () | |||
checkFormula env (P.And x y) = checkFormula env x *> checkFormula env y | |||
checkFormula env (P.Or x y) = checkFormula env x *> checkFormula env y | |||
checkFormula env (P.Is0 x) = | |||
case Map.lookup x (names env) of | |||
Just (ty, _) -> unifyTC env ty VI | |||
Nothing -> throwIO (NotInScope x) | |||
checkFormula env (P.Is1 x) = | |||
case Map.lookup x (names env) of | |||
Just (ty, _) -> unifyTC env ty VI | |||
Nothing -> throwIO (NotInScope x) | |||
index_t :: Value | |||
index_t = VPi "_" VI (const VType) |
@ -0,0 +1,456 @@ | |||
{-# LANGUAGE ViewPatterns #-} | |||
{-# LANGUAGE DeriveAnyClass #-} | |||
{-# LANGUAGE BlockArguments #-} | |||
{-# LANGUAGE LambdaCase #-} | |||
module Eval where | |||
import Syntax | |||
import qualified Data.Map.Strict as Map | |||
import Data.Foldable | |||
import Control.Exception | |||
import Data.Typeable | |||
import System.IO.Unsafe (unsafePerformIO) | |||
import Data.IORef | |||
import Systems | |||
import Presyntax (Formula) | |||
import qualified Presyntax as P | |||
import Data.Maybe | |||
import Debug.Trace | |||
import GHC.Stack | |||
iand :: Value -> Value -> Value | |||
iand = \case | |||
VI1 -> id | |||
VI0 -> const VI0 | |||
x -> \case | |||
VI0 -> VI0 | |||
VI1 -> x | |||
y -> VIAnd x y | |||
ior :: Value -> Value -> Value | |||
ior = \case | |||
VI0 -> id | |||
VI1 -> const VI1 | |||
x -> \case | |||
VI1 -> VI1 | |||
VI0 -> x | |||
y -> VIOr x y | |||
inot :: Value -> Value | |||
inot VI1 = VI0 | |||
inot VI0 = VI1 | |||
inot (VIOr x y) = iand (inot x) (inot y) | |||
inot (VIAnd x y) = ior (inot x) (inot y) | |||
inot (VINot x) = x | |||
inot x = VINot x | |||
(@@) :: Value -> Value -> Value | |||
VNe hd xs @@ vl = VNe hd (PApp vl:xs) | |||
VLam _ _ k @@ vl = k vl | |||
VEqGlued a b @@ vl = VEqGlued (a @@ vl) (b @@ vl) | |||
VOfSub a phi u0 x @@ vl = x @@ vl | |||
f @@ _ = error $ "can't apply argument to " ++ show f | |||
proj1 :: Value -> Value | |||
proj1 (VPair x _) = x | |||
proj1 (VEqGlued x y) = VEqGlued (proj1 x) (proj1 y) | |||
proj1 (VNe s xs) = VNe s (PProj1:xs) | |||
proj1 (VOfSub (VSigma _ d _) phi u0 x) = VOfSub d phi (proj1 u0) (proj1 x) | |||
proj1 x = error $ "can't proj1 " ++ show x | |||
proj2 :: Value -> Value | |||
proj2 (VPair _ y) = y | |||
proj2 (VEqGlued x y) = VEqGlued (proj1 x) (proj1 y) | |||
proj2 (VNe s xs) = VNe s (PProj2:xs) | |||
proj2 (VOfSub (VSigma _ d r) phi u0 x) = | |||
VOfSub (r (proj1 x)) phi (proj2 u0) (proj2 x) | |||
proj2 x = error $ "can't proj2 " ++ show x | |||
pathp :: Env -> Value -> Value -> Value -> Value -> Value -> Value | |||
pathp env p x y f@(VLine _a _x _y e) i = | |||
case reduceCube env i of | |||
Just P.Bot -> VEqGlued (e i) x | |||
Just P.Top -> VEqGlued (e i) y | |||
_ -> e i | |||
pathp env p x y (VEqGlued e e') i = VEqGlued (pathp env p x y e i) (pathp env p x y e' i) | |||
pathp env p x y (VNe hd sp) i = | |||
case reduceCube env i of | |||
Just P.Bot -> VEqGlued (VNe hd (PPathP p x y i:sp)) x | |||
Just P.Top -> VEqGlued (VNe hd (PPathP p x y i:sp)) y | |||
_ -> VNe hd (PPathP p x y i:sp) | |||
pathp env p x y (VOfSub _ _ _ v) i = pathp env p x y v i | |||
comp :: Env -> Value -> Formula -> Value -> Value -> Value | |||
comp env a@(VLam ivar VI fam) phi u a0 = go (fam undefined) phi u a0 where | |||
i = VVar ivar | |||
stuck :: Value | |||
stuck = maybeAddEq $ VComp a (toValue phi) u a0 | |||
maybeAddEq :: Value -> Value | |||
maybeAddEq = | |||
if phi == P.Top | |||
then flip VEqGlued (u @@ VI1) | |||
else id | |||
go :: HasCallStack => Value -> Formula -> Value -> Value -> Value | |||
go VPi{} phi u a0 = | |||
let | |||
dom x = let VPi _ d _ = fam x in d | |||
rng x = let VPi _ d _ = fam x in d | |||
ai1 = dom VI0 | |||
y' i y = fill env i (dom . inot . fam) P.Bot (VSystem emptySystem) y | |||
ybar i y = y' (inot i) y | |||
in VLam "x" ai1 \arg -> | |||
comp env | |||
(VLam ivar VI (\i -> rng (ybar i arg))) | |||
phi | |||
(VLam "i" VI \i -> mapVSystem (u @@ i) (@@ ybar i arg)) | |||
(a0 @@ ybar VI0 arg) | |||
go VSigma{} phi u a0 = | |||
let | |||
dom x = let VSigma _ d _ = fam x in d | |||
rng x = let VSigma _ d _ = fam x in d | |||
a i = fill env i (dom . fam) phi (VLam "j" VI \v -> mapVSystem (u @@ v) proj1) (proj1 a0) | |||
c1 = comp env (VLam ivar VI (getd . fam)) phi (VLam "i" VI \v -> mapVSystem (u @@ v) proj1) (proj1 a0) | |||
c2 = comp env (VLam ivar VI (apr (a VI1) . fam)) phi (VLam "i" VI \v -> mapVSystem (u @@ v) proj2) (proj2 a0) | |||
getd (VSigma _ d _) = d | |||
apr x (VSigma _ _ r) = r x | |||
in VPair c1 c2 | |||
go VPath{} phi p p0 = | |||
let | |||
~(VPath ai1 u1 v1) = fam VI1 | |||
~(VPath ai0 u0 v0) = fam VI0 | |||
getA (VPath a _ _) = a | |||
u' x = let ~(VPath _ u _) = fam x in u | |||
v' x = let ~(VPath _ _ v) = fam x in v | |||
in | |||
VLine (ai1 @@ VI1) u1 v1 \j -> | |||
let | |||
jc = reduceCube' env j | |||
in comp env (VLam ivar VI (getA . fam)) | |||
(orFormula [phi, jc, notFormula jc]) | |||
(VLam "j" VI \v -> | |||
let | |||
VSystem (FMap sys) = p @@ v | |||
sys' = fmap (flip (pathp env ai0 u0 v0) j) sys | |||
in mkVSystem $ Map.fromList [(phi, mapVSystem (p @@ v) (flip (pathp env ai0 u0 v0) j)) | |||
, (notFormula jc, u' v), (jc, v' v)]) | |||
(pathp env (ai0 @@ VI0) u0 v0 p0 j) | |||
go a P.Top u a0 = u @@ VI1 | |||
go a phi u a0 = maybeAddEq stuck | |||
comp env va phi u a0 = | |||
if phi == P.Top | |||
then VEqGlued (VComp va phi' u a0) (u @@ VI1) | |||
else VComp va phi' u a0 | |||
where | |||
phi' = toValue phi | |||
mkVSystem :: Map.Map Formula Value -> Value | |||
mkVSystem mp | |||
| Just e <- Map.lookup P.Top mp = e | |||
| otherwise = VSystem $ FMap $ Map.filterWithKey f mp | |||
where | |||
f P.Bot _ = False | |||
f _ _ = True | |||
reduceCube' :: Env -> Value -> Formula | |||
reduceCube' env = fromJust . reduceCube env | |||
mapVSystem :: Value -> (Value -> Value) -> Value | |||
mapVSystem (VSystem ss) f = VSystem (mapSystem ss f) | |||
mapVSystem x f = f x | |||
evalSystem :: Env -> Map.Map Formula Term -> Value | |||
evalSystem env face = mk . Map.mapMaybeWithKey go $ face where | |||
go :: Formula -> Term -> Maybe Value | |||
go face tm | |||
| VI0 <- toValue' env face = Nothing | |||
| otherwise = Just (eval env tm) | |||
differsFromEnv :: String -> Bool -> Bool | |||
differsFromEnv x True = | |||
case Map.lookup x (names env) of | |||
Just (VI, VI0) -> True | |||
_ -> False | |||
differsFromEnv x False = | |||
case Map.lookup x (names env) of | |||
Just (VI, VI1) -> True | |||
_ -> False | |||
mk x = case Map.toList x of | |||
[(_, x)] -> x | |||
_ -> mkVSystem x | |||
eval :: Env -> Term -> Value | |||
eval env = \case | |||
Var v -> | |||
case Map.lookup v (names env) of | |||
Just (_, vl) -> vl | |||
Nothing -> error $ "variable not in scope: " ++ show v | |||
App f x -> eval env f @@ eval env x | |||
Lam s d b -> | |||
let d' = eval env d | |||
in VLam s d' \a -> eval env{ names = Map.insert s (d', a) (names env) } b | |||
Let s t b d -> | |||
let b' = eval env b | |||
t' = eval env t | |||
in eval env{ names = Map.insert s (t', b') (names env) } d | |||
Pi s d r -> | |||
let d' = eval env d | |||
in VPi s d' \a -> eval env{ names = Map.insert s (d', a) (names env) } r | |||
Sigma s d r -> | |||
let d' = eval env d | |||
in VSigma s d' \a -> eval env{ names = Map.insert s (d', a) (names env) } r | |||
Pair a b -> VPair (eval env a) (eval env b) | |||
Proj1 x -> proj1 (eval env x) | |||
Proj2 y -> proj2 (eval env y) | |||
Type -> VType | |||
I -> VI | |||
I0 -> VI0 | |||
I1 -> VI1 | |||
Path p x y -> VPath (eval env p) (eval env x) (eval env y) | |||
Partial r a -> VPartial (eval env r) (eval env a) | |||
PathI p x y s e -> VLine (eval env p) (eval env x) (eval env y) (\ a -> eval env{ names = Map.insert s (VI, a) (names env) } e) | |||
PathP p x y f i -> pathp env (eval env p) (eval env x) (eval env y) (eval env f) (eval env i) | |||
Sub p x y -> VSub (eval env p) (eval env x) (eval env y) | |||
InclSub a phi u a0 -> VOfSub (eval env a) (eval env phi) (eval env u) (eval env a0) | |||
IAnd x y -> iand (eval env x) (eval env y) | |||
IOr x y -> ior (eval env x) (eval env y) | |||
INot x -> inot (eval env x) | |||
Comp a phi u a0 -> | |||
case reduceCube env (eval env phi) of | |||
Just formula -> comp env (eval env a) formula (eval env u) (eval env a0) | |||
Nothing -> VComp (eval env a) (eval env phi) (eval env u) (eval env a0) | |||
System fs -> evalSystem env (getSystem fs) | |||
data UnifyError | |||
= Mismatch Value Value | |||
| NotPiType Value | |||
| NotPartialType Formula Value | |||
| NotSigmaType Value | |||
deriving (Show, Typeable, Exception) | |||
unify :: Env -> Value -> Value -> IO () | |||
unify env (VEqGlued a b) c = | |||
unify env a c `catch` \e -> const (unify env b c) (e :: UnifyError) | |||
unify env c (VEqGlued a b) = | |||
unify env c a `catch` \e -> const (unify env c b) (e :: UnifyError) | |||
unify env (VLine a x y f) e = unify env (f (VVar "i")) (pathp env a x y e (VVar "i")) | |||
unify env e (VLine a x y f) = unify env (f (VVar "i")) (pathp env a x y e (VVar "i")) | |||
unify env (VPartial r b) (VPartial r' b') = do | |||
unify env b b' | |||
case sameCube env r r' of | |||
Just True -> pure () | |||
_ -> unify env r r' | |||
unify env (VPartial r b) x = do | |||
case sameCube env r VI1 of | |||
Just True -> pure () | |||
_ -> unify env r VI1 | |||
unify env b x | |||
unify env x (VPartial r b) = do | |||
case sameCube env r VI1 of | |||
Just True -> pure () | |||
_ -> unify env r VI1 | |||
unify env x b | |||
unify env (VSub a phi _u0) vl = unify env a vl | |||
unify env u1 (VOfSub _a phi u0 a) = do | |||
case sameCube env phi VI1 of | |||
Just True -> unify env u1 u0 | |||
_ -> unify env u1 a | |||
unify env (VOfSub _a phi u0 a) u1 = do | |||
case sameCube env phi VI1 of | |||
Just True -> unify env u1 u0 | |||
_ -> unify env u1 a | |||
unify env vl1@(VNe x sp) vl2@(VNe y sp') | |||
| x == y = traverse_ (uncurry unifySp) (zip sp sp') | |||
| otherwise = throwIO $ Mismatch vl1 vl2 | |||
where | |||
unifySp (PApp x) (PApp y) = unify env x y | |||
unifySp (PPathP _a _x _y i) (PPathP _a' _x' _y' i') = unify env i i' | |||
unifySp PProj1 PProj1 = pure () | |||
unifySp PProj2 PProj2 = pure () | |||
unify env (VLam x _ k) e = unify env (k (VVar x)) (e @@ VVar x) | |||
unify env e (VLam x _ k) = unify env (e @@ VVar x) (k (VVar x)) | |||
unify env (VPi x d r) (VPi _ d' r') = do | |||
unify env d d' | |||
unify env (r (VVar x)) (r' (VVar x)) | |||
unify env (VSigma x d r) (VSigma _ d' r') = do | |||
unify env d d' | |||
unify env (r (VVar x)) (r' (VVar x)) | |||
unify env VType VType = pure () | |||
unify env VI VI = pure () | |||
unify env (VPair a b) (VPair c d) = unify env a c *> unify env b d | |||
unify env (VPath a x y) (VPath a' x' y') = unify env a a' *> unify env x x' *> unify env y y' | |||
unify env (VSystem fs) vl | |||
| ((_, vl'):_) <- Map.toList (Map.filterWithKey (\f _ -> isTrue (toValue' env f)) (getSystem fs)) | |||
= unify env vl' vl | |||
unify env vl (VSystem fs) | |||
| ((_, vl'):_) <- Map.toList (Map.filterWithKey (\f _ -> isTrue (toValue' env f)) (getSystem fs)) | |||
= unify env vl' vl | |||
unify env x y = | |||
case sameCube env x y of | |||
Just True -> pure () | |||
_ -> throwIO $ Mismatch x y | |||
reduceCube :: Env -> Value -> Maybe Formula | |||
reduceCube env x = fmap (toDNF . simplify) (toFormula x) where | |||
simplify :: Formula -> Formula | |||
simplify (P.Is0 x) = | |||
case Map.lookup x (names env) of | |||
Just (VI, VI0) -> P.Top | |||
Just (VI, VI1) -> P.Bot | |||
_ -> P.Is0 x | |||
simplify (P.Is1 x) = | |||
case Map.lookup x (names env) of | |||
Just (VI, VI1) -> P.Top | |||
Just (VI, VI0) -> P.Bot | |||
_ -> P.Is0 x | |||
simplify (P.And x y) = P.And (simplify x) (simplify y) | |||
simplify (P.Or x y) = P.Or (simplify x) (simplify y) | |||
simplify x = x | |||
sameCube :: Env -> Value -> Value -> Maybe Bool | |||
sameCube env x y = | |||
case (reduceCube env x, reduceCube env y) of | |||
(Just x, Just y) -> Just (x == y) | |||
_ -> Nothing | |||
toFormula :: Value -> Maybe Formula | |||
toFormula VI0 = Just P.Bot | |||
toFormula VI1 = Just P.Top | |||
toFormula (VNe x []) = Just (P.Is1 x) | |||
toFormula (VINot f) = notFormula <$> toFormula f | |||
toFormula (VIAnd x y) = do | |||
s <- toFormula y | |||
t <- toFormula x | |||
pure $ andFormula [s, t] | |||
toFormula (VIOr x y) = do | |||
s <- toFormula y | |||
t <- toFormula x | |||
pure $ orFormula [s, t] | |||
toFormula _ = Nothing | |||
faceInEnv :: Env -> Face -> Bool | |||
faceInEnv e f = Map.isSubmapOf (getFace f) (faceOfEnv (names e)) where | |||
faceOfEnv = Map.map (\(_, v) -> case v of { VI1 -> True; VEqGlued _ VI1 -> True; _ -> False }) . Map.filter (\(_, v) -> isI v) | |||
isI VI1 = True | |||
isI VI0 = True | |||
isI (VEqGlued _ x) = isI x | |||
isI _ = False | |||
isPiType :: Value -> IO (String, Value, Value -> Value) | |||
isPiType (VPi x d r) = pure (x, d, r) | |||
isPiType x = throwIO $ NotPiType x | |||
isSigmaType :: Value -> IO (String, Value, Value -> Value) | |||
isSigmaType (VSigma x d r) = pure (x, d, r) | |||
isSigmaType x = throwIO $ NotSigmaType x | |||
isPiOrPathType :: Value -> IO (Either (String, Value, Value -> Value) (Value, Value, Value)) | |||
isPiOrPathType (VPi x d r) = pure (Left (x, d, r)) | |||
isPiOrPathType (VPath x d r) = pure (Right (x, d, r)) | |||
isPiOrPathType x = throwIO $ NotPiType x | |||
isPartialType :: Formula -> Value -> IO (Formula, Value) | |||
isPartialType f p@(VPartial x y) = | |||
case toFormula x of | |||
Just x -> pure (x, y) | |||
Nothing -> throwIO $ NotPartialType f p | |||
isPartialType f x = throwIO $ NotPartialType f x | |||
getVar :: IO Value | |||
getVar = | |||
do | |||
n <- atomicModifyIORef ref \x -> (x + 1, x) | |||
pure (VVar (show n)) | |||
where | |||
ref :: IORef Int | |||
ref = unsafePerformIO (newIORef 0) | |||
{-# NOINLINE ref #-} | |||
fill :: Env | |||
-> Value | |||
-> (Value -> Value) -- (Γ i : I, A : Type) | |||
-> Formula -- (phi : I) | |||
-> Value -- (u : (i : I) -> Partial phi (A i)) | |||
-> Value -- (Sub (A i0) phi (u i0)) | |||
-> Value -- -> A i | |||
fill env i a phi u a0 = | |||
comp env | |||
(VLam "j" VI \j -> a (i `iand` j)) | |||
(phi `P.Or` ifc) | |||
(VLam "j" VI \j -> | |||
mkVSystem (Map.fromList [ (phi, uiand j) | |||
, (notFormula ifc, a0) ])) | |||
a0 | |||
where | |||
uiand j = u @@ (i `iand` j) | |||
ifc = fromJust (reduceCube env i) | |||
toValue :: Formula -> Value | |||
toValue P.Top = VI1 | |||
toValue P.Bot = VI0 | |||
toValue (P.And x y) = toValue x `iand` toValue y | |||
toValue (P.Or x y) = toValue x `ior` toValue y | |||
toValue (P.Is0 x) = inot (VVar x) | |||
toValue (P.Is1 x) = VVar x | |||
toValue' :: Env -> Formula -> Value | |||
toValue' env P.Top = VI1 | |||
toValue' env P.Bot = VI0 | |||
toValue' env (P.And x y) = toValue x `iand` toValue y | |||
toValue' env (P.Or x y) = toValue x `ior` toValue y | |||
toValue' env (P.Is0 x) = | |||
case Map.lookup x (names env) of | |||
Just (VI, VI0) -> VI1 | |||
Just (VI, VI1) -> VI0 | |||
Just (VI, x) -> inot x | |||
_ -> error $ "type error in toValue'" | |||
toValue' env (P.Is1 x) = | |||
case Map.lookup x (names env) of | |||
Just (VI, x) -> x | |||
_ -> error $ "type error in toValue'" | |||
isTrue :: Value -> Bool | |||
isTrue VI1 = True | |||
isTrue _ = False |
@ -0,0 +1,134 @@ | |||
{-# LANGUAGE LambdaCase #-} | |||
module Main where | |||
import Presyntax.Parser | |||
import Elab | |||
import Control.Monad.Catch | |||
import System.Exit | |||
import Syntax | |||
import System.Console.Haskeline (runInputT, defaultSettings, getInputLine) | |||
import Control.Monad.IO.Class | |||
import Presyntax | |||
import qualified Data.Map.Strict as Map | |||
import Eval (eval, UnifyError (..)) | |||
import Systems (formulaOfFace, Face) | |||
import Data.List | |||
showTypeError :: Maybe [String] -> Elab.TypeError -> String | |||
showTypeError lines (NotInScope l_c) = "Variable not in scope: " ++ l_c | |||
showTypeError lines (UnifyError (NotPiType vl)) = "Not a function type: " ++ show vl | |||
showTypeError lines (UnifyError (NotSigmaType vl)) = "Not a sigma type: " ++ show vl | |||
showTypeError lines (UnifyError (Mismatch a b)) = | |||
unlines [ "Types are not equal: " | |||
, " " ++ show (quote a) | |||
, " vs " | |||
, " " ++ show (quote b) | |||
] | |||
showTypeError lines (WrongFaces _ faces) = unlines (map face faces) where | |||
face :: ([Value], Value, Elab.TypeError) -> String | |||
face (ixs, rhs, err) = | |||
"When checking face described by " ++ show ixs ++ ":\n" ++ showTypeError Nothing err | |||
showTypeError lines (InSpan start end err) | |||
| Just lines <- lines, fst start == fst end | |||
= makeRange (lines !! fst start) start end ++ '\n':showTypeError Nothing err | |||
| otherwise = showTypeError Nothing err | |||
showTypeError lines (IncompleteSystem formula extent) = | |||
unlines $ | |||
[ "Incomplete system: " | |||
, "it is defined by " ++ show formula | |||
, "but the context mandates extent " ++ show extent ] | |||
showTypeError lines (IncompatibleFaces (fa, ta) (fb, tb) err) = | |||
unlines [ showTypeError lines err | |||
, "while checking that these overlapping faces are compatible:" | |||
, "* " ++ show fa ++ " -> " ++ show ta | |||
, "* " ++ show fb ++ " -> " ++ show tb | |||
] | |||
showTypeError _ x = show x | |||
makeRange :: String -> (Int, Int) -> (Int, Int) -> String | |||
makeRange line (_, sc) (_, ec) = line ++ "\n" ++ replicate (sc + 1) ' ' ++ replicate (ec - sc) '~' | |||
main :: IO () | |||
main = do | |||
code <- readFile "test.itt" | |||
case parseString body code of | |||
Left e -> print e | |||
Right x -> do | |||
(tm, _) <- infer (Env mempty ) x `catch` \e -> do | |||
putStrLn $ showTypeError (Just (lines code)) e | |||
exitFailure | |||
print tm | |||
repl :: IO () | |||
repl = runInputT defaultSettings (go (Env mempty)) where | |||
go env = getInputLine "λ " >>= \case | |||
Just i | ":sq " `isPrefixOf` i -> do | |||
case parseString body (replicate 4 ' ' ++ drop 4 i) of | |||
Right exp -> | |||
(do | |||
(tm, ty) <- liftIO $ infer env exp | |||
liftIO $ drawExtent ty (eval env tm) | |||
`catch` \e -> liftIO $ putStrLn (showTypeError (Just [i]) e)) | |||
`catch` \e -> liftIO $ print (e :: SomeException) | |||
Left e -> liftIO (print e) | |||
go env | |||
Just i -> | |||
case parseString statement i of | |||
Left e -> liftIO (print e) *> go env | |||
Right (Assume vs) -> | |||
let | |||
loop env ((v, t):vs) = do | |||
tm <- liftIO $ check env t VType | |||
let ty = eval env tm | |||
loop env{ names = Map.insert v (ty, VVar v) (names env) } vs | |||
loop env [] = go env | |||
in (loop env vs | |||
`catch` \e -> (liftIO $ putStrLn (showTypeError (Just [i]) e)) *> go env) | |||
`catch` \e -> (liftIO $ print (e :: SomeException)) *> go env | |||
Right (Eval v) -> do | |||
liftIO $ | |||
(do | |||
(tm, ty) <- infer env v | |||
let v_nf = eval env tm | |||
putStrLn $ show v_nf ++ " : " ++ show ty | |||
`catch` \e -> putStrLn (showTypeError (Just [i]) e)) | |||
`catch` \e -> print (e :: SomeException) | |||
go env | |||
Right (Declare n t e) -> do | |||
(do | |||
t <- liftIO $ check env t VType | |||
let t' = eval env t | |||
b <- liftIO $ check env e t' | |||
let b' = eval env b | |||
go env{ names = Map.insert n (t', b') (names env) }) | |||
`catch` \e -> (liftIO $ putStrLn (showTypeError (Just [i]) e)) *> go env | |||
`catch` \e -> (liftIO $ print (e :: SomeException)) *> go env | |||
Nothing -> pure () | |||
drawExtent :: Value -> Value -> IO () | |||
drawExtent ty vl = nicely $ getDirections ty vl where | |||
getDirections :: Value -> Value -> [([(String, Bool)], Value, Value)] | |||
getDirections (VPi _ VI r) (VLam s VI k) = | |||
let trues = getDirections (r VI1) (k VI1) | |||
falses = getDirections (r VI0) (k VI0) | |||
in map (\(p, t, v) -> ((s, True):p, t, v)) trues | |||
++ map (\(p, t, v) -> ((s, False):p, t, v)) falses | |||
getDirections ty t = [([], ty, t)] | |||
nicely :: [([(String, Bool)], Value, Value)] -> IO () | |||
nicely [] = pure () | |||
nicely ((bs, ty, el):fcs) = do | |||
putStr . unwords $ theFace bs | |||
putStrLn $ " => " ++ show el ++ " : " ++ show ty | |||
nicely fcs | |||
theFace = map (\(i, b) -> | |||
if b | |||
then "(" ++ i ++ "1)" | |||
else "(" ++ i ++ "0)") |
@ -0,0 +1,71 @@ | |||
{-# LANGUAGE LambdaCase #-} | |||
module Presyntax where | |||
data Exp | |||
= Var String | |||
| App Exp Exp | |||
| Lam String Exp | |||
| Let String Exp Exp Exp | |||
| Sigma String Exp Exp | |||
| Pair Exp Exp | |||
| Proj1 Exp | |||
| Proj2 Exp | |||
| Pi String Exp Exp | |||
| Type | |||
| I | |||
| I0 | I1 | |||
| IAnd Exp Exp | |||
| IOr Exp Exp | |||
| INot Exp | |||
| Path | |||
| Cut Exp Exp | |||
| Span (Int, Int) (Int, Int) Exp | |||
-- Formulas, partial elements, and the type of formulas | |||
| Partial [(Formula, Exp)] | |||
| PartialT | |||
-- Compositions | |||
| Comp | |||
-- Cubical subtypes | |||
| SubT | |||
deriving (Eq, Show, Ord) | |||
data Formula | |||
= Is0 String | |||
| Is1 String | |||
| And Formula Formula | |||
| Or Formula Formula | |||
| Top | Bot | |||
deriving (Eq, Ord) | |||
instance Show Formula where | |||
showsPrec p = | |||
\case | |||
Is1 i -> showString i | |||
Is0 i -> showString ('~':i) | |||
And x y -> showParen (p > and_prec) $ | |||
showsPrec or_prec x | |||
. showString " && " | |||
. showsPrec or_prec y | |||
Or x y -> showParen (p > or_prec) $ | |||
showsPrec or_prec x | |||
. showString " || " | |||
. showsPrec or_prec y | |||
Top -> showString "i1" | |||
Bot -> showString "i0" | |||
where | |||
and_prec = 2 | |||
or_prec = 1 | |||
data Statement | |||
= Assume [(String, Exp)] | |||
| Declare String Exp Exp | |||
| Eval Exp |
@ -0,0 +1,192 @@ | |||
{-# 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_path | |||
| Tok_phi | |||
| Tok_sub | |||
| Tok_comp | |||
| Tok_tr | |||
| Tok_I | |||
| Tok_I0 | |||
| Tok_I1 | |||
| Tok_oparen | |||
| Tok_cparen | |||
| Tok_osquare | |||
| Tok_csquare | |||
| Tok_colon | |||
| Tok_arrow | |||
| Tok_let | |||
| Tok_equal | |||
| Tok_in | |||
| Tok_and | |||
| Tok_not | |||
| Tok_or | |||
| Tok_fand | |||
| Tok_for | |||
| Tok_assume | |||
| Tok_p1 | |||
| Tok_p2 | |||
| Tok_comma | |||
| Tok_times | |||
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_not `yield` go (off + 1) line (col + 1) cs | |||
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_osquare `yield` go (off + 1) line (col + 1) cs | |||
go !off !line !col (']':cs) = | |||
Token line col off (off + 1) Tok_csquare `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_comma `yield` go (off + 1) line (col + 1) 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 + 2) Tok_for `yield` go (off + 2) line (col + 2) 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_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 ('&':'&':cs) = | |||
Token line col off (off + 2) Tok_and `yield` go (off + 2) line (col + 2) cs | |||
go !off !line !col ('&':cs) = | |||
Token line col off (off + 1) Tok_fand `yield` go (off + 1) line (col + 1) cs | |||
go !off !line !col ('/':'\\':cs) = | |||
Token line col off (off + 1) Tok_fand `yield` go (off + 1) line (col + 1) cs | |||
go !off !line !col ('|':'|':cs) = | |||
Token line col off (off + 2) Tok_or `yield` go (off + 2) line (col + 2) cs | |||
go !off !line !col ('|':cs) = | |||
Token line col off (off + 1) Tok_for `yield` go (off + 1) line (col + 1) cs | |||
go !off !line !col ('.':'1':cs) = | |||
Token line col off (off + 2) Tok_p1 `yield` go (off + 2) line (col + 2) cs | |||
go !off !line !col ('.':'2':cs) = | |||
Token line col off (off + 2) Tok_p2 `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 + 2) line (col + 2) cs | |||
| otherwise = skipComment (off + 2) line (col + 2) (level - 1) cs | |||
skipComment off line col level ('{':'-':cs) = | |||
skipComment (off + 2) line (col + 2) (level + 1) cs | |||
skipComment off line col level ('\n':cs) = | |||
skipComment (off + 1) (line + 1) 0 level cs | |||
skipComment off line col level (c:cs) = | |||
skipComment (off + 1) line (col + 1) level cs | |||
skipComment _ line col _ [] = Left (EOFInComment line col) | |||
yield c = fmap (c:) | |||
finishIdent c | |||
| T.pack "Type" == c = Tok_type | |||
| T.pack "Path" == c = Tok_path | |||
| T.pack "Partial" == c = Tok_phi | |||
| T.pack "Sub" == c = Tok_sub | |||
| T.pack "comp" == c = Tok_comp | |||
| T.pack "tr" == c = Tok_tr | |||
| T.pack "I" == c = Tok_I | |||
| T.pack "i0" == c = Tok_I0 | |||
| T.pack "i1" == c = Tok_I1 | |||
| T.pack "let" == c = Tok_let | |||
| T.pack "in" == c = Tok_in | |||
| T.pack "assume" == c = Tok_assume | |||
| otherwise = Tok_var c |
@ -0,0 +1,284 @@ | |||
{-# 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 | |||
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)) | |||
eof :: Parser () | |||
eof = Parser $ \state -> | |||
case ptTs state of | |||
[] -> Right ((), state) | |||
(x:_) -> Left (Unexpected x) | |||
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 | |||
parens :: Parser a -> Parser a | |||
parens k = do | |||
expect Tok_oparen | |||
x <- k | |||
expect Tok_cparen | |||
pure x | |||
square :: Parser a -> Parser a | |||
square k = do | |||
expect Tok_osquare | |||
x <- k | |||
expect Tok_csquare | |||
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 Exp -> Parser Exp | |||
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 (Span start end x) | |||
body :: Parser Exp | |||
body = attachPos letExpr <|> attachPos lamExpr <|> attachPos exprPi where | |||
lamExpr = do | |||
expect Tok_lambda | |||
vs <- some arg | |||
expect Tok_arrow | |||
e <- body | |||
pure (foldr Lam e vs) | |||
letExpr = do | |||
expect Tok_let | |||
v <- T.unpack <$> var | |||
expect Tok_colon | |||
t <- body | |||
expect Tok_equal | |||
b <- body | |||
expect Tok_in | |||
Let v t b <$> body | |||
arg = T.unpack <$> var | |||
exprPi :: Parser Exp | |||
exprPi = attachPos $ | |||
do | |||
bs <- optionally binder | |||
case bs of | |||
Just k -> foldl (.) id k <$> attachPos exprPi | |||
Nothing -> attachPos exprArr | |||
where | |||
binder = (some (parens bind) <* expect Tok_arrow) | |||
<|> (fmap pure (parens sigma) <* expect Tok_times) | |||
bind = do | |||
names <- some (T.unpack <$> var) | |||
expect Tok_colon | |||
t <- exprPi | |||
pure (foldr (\n k -> Pi n t . k) id names) | |||
sigma = do | |||
names <- some (T.unpack <$> var) | |||
expect Tok_colon | |||
t <- exprPi | |||
pure (foldr (\n k -> Sigma n t . k) id names) | |||
exprArr :: Parser Exp | |||
exprArr = attachPos $ do | |||
t <- attachPos exprConj | |||
c <- optionally (fmap (const True) (expect Tok_arrow) <|> fmap (const False) (expect Tok_times)) | |||
case c of | |||
Just True -> Pi "_" t <$> exprPi | |||
Just False -> Sigma "_" t <$> exprPi | |||
Nothing -> pure t | |||
exprApp :: Parser Exp | |||
exprApp = attachPos $ | |||
do | |||
head <- atom | |||
spine <- many spineEntry | |||
pure (foldl app head spine) | |||
where | |||
spineEntry = atom | |||
app f s = App f s | |||
exprDisj :: Parser Exp | |||
exprDisj = attachPos $ | |||
do | |||
first <- exprApp | |||
rest <- many disjunct | |||
pure (foldl IOr first rest) | |||
where | |||
disjunct = expect Tok_or *> exprApp | |||
exprConj :: Parser Exp | |||
exprConj = attachPos $ | |||
do | |||
first <- exprDisj | |||
rest <- many conjunct | |||
pure (foldl IAnd first rest) | |||
where | |||
conjunct = expect Tok_and *> exprDisj | |||
atom0 :: Parser Exp | |||
atom0 = attachPos $ | |||
fmap (Var . T.unpack) var | |||
<|> fmap (const Type) (expect Tok_type) | |||
<|> fmap (const I) (expect Tok_I) | |||
<|> fmap (const I0) (expect Tok_I0) | |||
<|> fmap (const I1) (expect Tok_I1) | |||
<|> fmap (const Path) (expect Tok_path) | |||
<|> fmap (const SubT) (expect Tok_sub) | |||
<|> fmap (const PartialT) (expect Tok_phi) | |||
<|> fmap (const Comp) (expect Tok_comp) | |||
<|> fmap INot (expect Tok_not *> atom) | |||
<|> parens pair | |||
<|> square (Partial <$> (system <|> pure [])) | |||
atom :: Parser Exp | |||
atom = attachPos $ | |||
do | |||
e <- atom0 | |||
c <- many (selectToken (projection . tokClass)) | |||
pure $ case c of | |||
[] -> e | |||
sls -> foldl (flip ($)) e sls | |||
where | |||
projection Tok_p1 = pure Proj1 | |||
projection Tok_p2 = pure Proj2 | |||
projection _ = Nothing | |||
system :: Parser [(Formula, Exp)] | |||
system = | |||
do | |||
t <- comp | |||
x <- optionally (expect Tok_comma) | |||
case x of | |||
Just () -> (t:) <$> system | |||
Nothing -> pure [t] | |||
where | |||
comp = do | |||
t <- formula | |||
expect Tok_arrow | |||
(t,) <$> body | |||
pair :: Parser Exp | |||
pair = do | |||
t <- body | |||
x <- optionally (expect Tok_comma) | |||
case x of | |||
Just () -> Pair t <$> pair | |||
Nothing -> pure t | |||
statement :: Parser Statement | |||
statement = (assume <|> declare <|> (Eval <$> body)) <* eof where | |||
assume = do | |||
expect Tok_assume | |||
Assume <$> vars | |||
declare = do | |||
expect Tok_let | |||
x <- T.unpack <$> var | |||
expect Tok_colon | |||
ty <- body | |||
expect Tok_equal | |||
Declare x ty <$> body | |||
bind = do | |||
var <- some (T.unpack <$> var) | |||
expect Tok_colon | |||
body <- body | |||
pure $ map ((, body)) var | |||
vars = do | |||
var <- bind | |||
t <- optionally (expect Tok_comma) | |||
case t of | |||
Nothing -> pure var | |||
Just x -> (var ++) <$> vars | |||
formula :: Parser Formula | |||
formula = conjunction where | |||
conjunction, disjunction, atom :: Parser Formula | |||
conjunction = do | |||
d <- disjunction | |||
t <- optionally (expect Tok_and) | |||
case t of | |||
Nothing -> pure d | |||
Just x -> And d <$> conjunction | |||
disjunction = do | |||
d <- atom | |||
t <- optionally (expect Tok_or) | |||
case t of | |||
Nothing -> pure d | |||
Just x -> Or d <$> disjunction | |||
atom = (Is1 . T.unpack) <$> var | |||
<|> (Is0 . T.unpack) <$> (expect Tok_not *> var) | |||
<|> Top <$ expect Tok_I1 | |||
<|> Bot <$ expect Tok_I0 |
@ -0,0 +1,250 @@ | |||
{-# LANGUAGE LambdaCase #-} | |||
{-# LANGUAGE PatternSynonyms #-} | |||
module Syntax where | |||
import Data.Set (Set) | |||
import qualified Data.Set as Set | |||
import Data.Map.Strict (Map) | |||
import Systems | |||
import qualified Data.Map.Strict as Map | |||
import Text.Show (showListWith) | |||
import Presyntax (Formula) | |||
type Space = Term | |||
data Term | |||
= Var String | |||
| App Term Term | |||
| Lam String Term Term | |||
| Let String Term Term Term | |||
| Pi String Term Term | |||
| Type | |||
| I | |||
| I0 | I1 | |||
| IAnd Term Term | |||
| IOr Term Term | |||
| INot Term | |||
| Path Space Term Term | |||
| PathI Space Term Term String Term | |||
| PathP Space Term Term Term Term | |||
| Sigma String Term Term | |||
| Pair Term Term | |||
| Proj1 Term | |||
| Proj2 Term | |||
| System (System Term) | |||
| Partial Term Term | |||
| Comp Term Term Term Term | |||
| Sub Term Term Term | |||
| InclSub Term Term Term Term | |||
deriving (Eq, Ord) | |||
instance Show Term where | |||
showsPrec p = | |||
\case | |||
Var s -> showString s | |||
System fs -> showListWith showPE (Map.toList (getSystem fs)) | |||
-- ew | |||
App (App (App (Lam _ _ (Lam _ _ (Lam _ _ Path{}))) a) x) y -> showsPrec p (Path a x y) | |||
App (App (App (Lam _ _ (Lam _ _ (Lam _ _ Sub{}))) a) x) y -> showsPrec p (Sub a x y) | |||
App (App (Lam _ _ (Lam _ _ Partial{})) phi) r -> showsPrec p (Partial phi r) | |||
App (App (App (App (Lam _ _ (Lam _ _ (Lam _ _ (Lam _ _ Comp{})))) a) phi) u) a0 -> | |||
showsPrec p (Comp a phi u a0) | |||
App f x -> showParen (p >= app_prec) $ | |||
showsPrec fun_prec f | |||
. showChar ' ' | |||
. showsPrec app_prec x | |||
Lam s t b -> | |||
let | |||
getLams (Lam s _ b) = | |||
let (as, b') = getLams b | |||
in (s:as, b') | |||
getLams (PathI _a _x _y s b) = | |||
let (as, b') = getLams b | |||
in (("(" ++ s ++ " : I)"):as, b') | |||
getLams t = ([], t) | |||
(args, bd) = getLams (Lam s t b) | |||
in showParen (p >= fun_prec) $ | |||
showString ("λ " ++ unwords args ++ " -> ") | |||
. shows bd | |||
Let s t d b -> showParen (p > fun_prec) $ | |||
showString "let\n " | |||
. showString s | |||
. showString " : " | |||
. shows t | |||
. showString " = " | |||
. shows d | |||
. showString " in " | |||
. shows b | |||
Pi "_" d r -> | |||
showParen (p >= domain_prec) $ | |||
showsPrec domain_prec d | |||
. showString " -> " | |||
. shows r | |||
Pi v d r -> showParen (p >= domain_prec) $ | |||
let | |||
showBinder (Pi "_" d r) = | |||
showsPrec domain_prec d | |||
. showString " -> " | |||
. shows r | |||
showBinder (Pi n d r) = | |||
let | |||
arr = case r of | |||
Pi n _ _ | n /= "_" -> " " | |||
_ -> " -> " | |||
in | |||
showParen True (showString n . showString " : " . shows d) | |||
. showString arr | |||
. showBinder r | |||
showBinder t = shows t | |||
in showBinder (Pi v d r) | |||
Type -> showString "Type" | |||
I -> showChar 'I' | |||
I0 -> showString "i0" | |||
I1 -> showString "i1" | |||
IAnd i j -> showParen (p >= and_prec) $ | |||
showsPrec or_prec i | |||
. showString " && " | |||
. showsPrec or_prec j | |||
IOr i j -> showParen (p >= or_prec) $ | |||
showsPrec app_prec i | |||
. showString " || " | |||
. showsPrec app_prec j | |||
INot s -> showChar '~' . showsPrec p s | |||
Path a x y -> showsPrec p (App (App (App (Var "Path") a) x) y) | |||
Sub a x y -> showsPrec p (App (App (App (Var "Sub") a) x) y) | |||
Partial r a -> showsPrec p (App (App (Var "Partial") r) a) | |||
Comp a phi u a0 -> showsPrec p (foldl App (Var "comp") [a, phi, u, a0]) | |||
InclSub _a _phi _u0 a0 -> showsPrec p a0 | |||
PathI a x y s b -> showParen (p >= fun_prec) $ | |||
showString ("λ " ++ s ++ " -> ") | |||
. shows b | |||
PathP _a _x _y f i -> showsPrec p (App f i) | |||
Pair a b -> showParen True $ | |||
shows a | |||
. showString ", " | |||
. shows b | |||
Proj1 b -> showsPrec p b . showString ".1" | |||
Proj2 b -> showsPrec p b . showString ".1" | |||
Sigma v d r -> | |||
showParen (p >= app_prec) $ | |||
showParen True (showString v . showString " : " . shows d) | |||
. showString " × " | |||
. shows r | |||
where | |||
app_prec = 6 | |||
domain_prec = 5 | |||
and_prec = 4 | |||
or_prec = 3 | |||
fun_prec = 1 | |||
showPE :: (Formula, Term) -> String -> String | |||
showPE (f, t) = shows f . showString " -> " . shows t | |||
data Value | |||
= VNe String [Proj] | |||
| VLam String Value (Value -> Value) | |||
| VPi String Value (Value -> Value) | |||
| VType | |||
| VI | VI0 | VI1 | |||
| VEqGlued Value Value -- e which is def. eq. to e' | |||
| VPair Value Value | |||
| VSigma String Value (Value -> Value) | |||
| VLine Value Value Value (Value -> Value) | |||
-- (λ i → ...) : Path A x y | |||
-- order: A x y k | |||
| VSystem (System Value) | |||
| VOfSub Value Value Value Value | |||
| VIAnd Value Value | |||
| VIOr Value Value | |||
| VINot Value | |||
| VPath Value Value Value | |||
| VSub Value Value Value | |||
| VPartial Value Value | |||
| VComp Value Value Value Value | |||
data Proj | |||
= PApp Value | |||
| PPathP Value Value Value Value | |||
-- a x y i | |||
| PProj1 | |||
| PProj2 | |||
pattern VVar :: String -> Value | |||
pattern VVar x = VNe x [] | |||
quote :: Value -> Term | |||
quote = go mempty where | |||
go :: Set String -> Value -> Term | |||
go scope (VNe hd spine) = foldl (goSpine scope) (Var hd) (reverse spine) | |||
go scope (VLam s a k) = | |||
let n = rename s scope | |||
in Lam n (go scope a) (go (Set.insert n scope) (k (VVar n))) | |||
go scope (VPi s d r) = | |||
let n = rename s scope | |||
in Pi n (go scope d) (go (Set.insert n scope) (r (VVar n))) | |||
go scope (VSigma s d r) = | |||
let n = rename s scope | |||
in Sigma n (go scope d) (go (Set.insert n scope) (r (VVar n))) | |||
go scope VType = Type | |||
go scope VI0 = I0 | |||
go scope VI1 = I1 | |||
go scope VI = I | |||
go scope (VIAnd x y) = IAnd (go scope x) (go scope y) | |||
go scope (VIOr x y) = IOr (go scope x) (go scope y) | |||
go scope (VINot x) = INot (go scope x) | |||
go scope (VPath a x y) = Path (go scope a) (go scope x) (go scope y) | |||
go scope (VSub a x y) = Sub (go scope a) (go scope x) (go scope y) | |||
go scope (VPartial r a) = Partial (go scope r) (go scope a) | |||
go scope (VComp a b c d) = Comp (go scope a) (go scope b) (go scope c) (go scope d) | |||
go scope (VEqGlued e _) = go scope e | |||
go scope (VPair a b) = Pair (go scope a) (go scope b) | |||
go scope (VLine a x y k) = | |||
let n = rename "i" scope | |||
in PathI (go scope a) (go scope x) (go scope y) n (go (Set.insert n scope) (k (VVar n))) | |||
go scope (VSystem (FMap fs)) = System (FMap (fmap (go scope) fs)) | |||
go scope (VOfSub _ _ _ x) = go scope x | |||
goSpine :: Set String -> Term -> Proj -> Term | |||
goSpine scope t (PApp x) = App t (go scope x) | |||
goSpine scope t (PPathP a x y i) = PathP (go scope a) (go scope x) (go scope y) t (go scope i) | |||
goSpine scope t PProj1 = Proj1 t | |||
goSpine scope t PProj2 = Proj2 t | |||
rename :: String -> Set String -> String | |||
rename x s | |||
| x == "_" = x | |||
| x `Set.member` s = rename (x ++ "'") s | |||
| otherwise = x | |||
instance Show Value where | |||
showsPrec p = showsPrec p . quote | |||
data Env = | |||
Env { names :: Map String (Value, Value) | |||
} | |||
deriving (Show) |
@ -0,0 +1,96 @@ | |||
module Systems where | |||
import Data.Map.Strict (Map) | |||
import Presyntax | |||
import qualified Data.Map.Strict as Map | |||
import Data.Set (Set) | |||
import qualified Data.Set as Set | |||
import Data.List | |||
newtype Face = Face { getFace :: Map String Bool } | |||
deriving (Eq, Show, Ord) | |||
evalFormula :: Formula -> Face -> Bool | |||
evalFormula (Is0 x) f = | |||
case Map.lookup x (getFace f) of | |||
Just x -> not x | |||
Nothing -> error $ "dimension not bound in formula: " ++ show x | |||
evalFormula (Is1 x) f = | |||
case Map.lookup x (getFace f) of | |||
Just x -> x | |||
Nothing -> error $ "dimension not bound in formula: " ++ show x | |||
evalFormula (And a b) f = evalFormula a f && evalFormula b f | |||
evalFormula (Or a b) f = evalFormula a f || evalFormula b f | |||
evalFormula Top _ = True | |||
evalFormula Bot _ = False | |||
freeVarsFormula :: Formula -> Set String | |||
freeVarsFormula (Is0 x) = Set.singleton x | |||
freeVarsFormula (Is1 x) = Set.singleton x | |||
freeVarsFormula (And a b) = Set.union (freeVarsFormula a) (freeVarsFormula b) | |||
freeVarsFormula (Or a b) = Set.union (freeVarsFormula a) (freeVarsFormula b) | |||
freeVarsFormula Top = mempty | |||
freeVarsFormula Bot = mempty | |||
faces :: Formula -> ([Face], [Face]) | |||
faces formula = partition (evalFormula formula) allPossible where | |||
truths [] = [mempty] | |||
truths (x:xs) = uncurry Map.insert <$> [(x, True), (x, False)] <*> truths xs | |||
allPossible = Face <$> truths (Set.toList (freeVarsFormula formula)) | |||
impossible, possible, tautological :: Formula -> Bool | |||
impossible = null . fst . faces | |||
possible = not . null . fst . faces | |||
tautological = not . null . snd . faces | |||
toDNF :: Formula -> Formula | |||
toDNF = orFormula . map formulaOfFace . fst . faces | |||
formulaOfFace :: Face -> Formula | |||
formulaOfFace = andFormula . map (\(x, i) -> if i then Is1 x else Is0 x) . Map.toDescList . getFace | |||
andFormula :: [Formula] -> Formula | |||
andFormula = foldr and Top where | |||
and x y = | |||
case x of | |||
Top -> case y of | |||
Bot -> Bot | |||
_ -> y | |||
Bot -> Bot | |||
_ -> case y of | |||
Top -> x | |||
_ -> And x y | |||
orFormula :: [Formula] -> Formula | |||
orFormula [] = Bot | |||
orFormula (x:xs) = or x (orFormula xs) where | |||
or x y = | |||
case x of | |||
Top -> Top | |||
Bot -> case y of | |||
Top -> Top | |||
_ -> y | |||
_ -> case y of | |||
Bot -> x | |||
_ -> Or x y | |||
notFormula :: Formula -> Formula | |||
notFormula Top = Bot | |||
notFormula Bot = Top | |||
notFormula (Is0 x) = Is1 x | |||
notFormula (Is1 x) = Is0 x | |||
notFormula (And x y) = Or (notFormula x) (notFormula y) | |||
notFormula (Or x y) = And (notFormula x) (notFormula y) | |||
newtype System a = FMap { getSystem :: Map Formula a } | |||
deriving (Eq, Show, Ord) | |||
emptySystem :: System a | |||
emptySystem = FMap mempty | |||
mapSystem :: System a -> (a -> b) -> System b | |||
mapSystem (FMap x) f = FMap (fmap f x) |
@ -0,0 +1,67 @@ | |||
# 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: | |||
url: https://raw.githubusercontent.com/commercialhaskell/stackage-snapshots/master/lts/17/1.yaml | |||
# 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.5" | |||
# | |||
# 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,13 @@ | |||
# 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: 563098 | |||
url: https://raw.githubusercontent.com/commercialhaskell/stackage-snapshots/master/lts/17/1.yaml | |||
sha256: 395775c03e66a4286f134d50346b0b6f1432131cf542886252984b4cfa5fef69 | |||
original: | |||
url: https://raw.githubusercontent.com/commercialhaskell/stackage-snapshots/master/lts/17/1.yaml |
@ -0,0 +1,52 @@ | |||
{- let | |||
sym : (A : Type) (x y : A) -> Path (\x -> A) x y -> Path (\x -> A) y x | |||
= λ A x y p i -> p (~ i) | |||
in let | |||
funext : (A : Type) (B : A -> Type) (f g : (x : A) -> B x) -> ((x : A) -> Path (\i -> B x) (f x) (g x)) -> Path (\i -> (x : A) -> B x) f g | |||
= λ A B f g h i x -> h x i | |||
in let | |||
i0IsI1 : Path (\x -> I) i0 i1 | |||
= λ i -> i | |||
in let | |||
singContr : (A : Type) (a b : A) (p : Path (\j -> A) a b) -> Path (\i -> (x : A) * (Path (\j -> A) a x)) (a, \i -> a) (b, p) | |||
= λ A a b p i -> (p i, λ j -> p (i && j)) | |||
in -} let | |||
transport : (A : I -> Type) (a : A i0) -> A i1 | |||
= \A a -> comp A i0 (\i -> []) a | |||
in {- let | |||
Jay : (A : Type) (x : A) | |||
(P : (y : A) -> Path (\i -> A) x y -> Type) | |||
(d : P x (\i -> x)) | |||
(y : A) (p : Path (\i -> A) x y) | |||
-> P y p | |||
= \A x P d y p -> transport (\i -> P (p i) (\j -> p (i && j))) d | |||
in -} | |||
let | |||
fill : (i : I) (A : I -> Type) | |||
(phi : I) (u : (i : I) -> Partial phi (A i)) | |||
-> Sub (A i0) phi (u i0) -> A i | |||
= \i A phi u a0 -> | |||
comp (\j -> A (i && j)) (phi || ~i) (\j -> [ phi -> u (i && j), ~i -> a0 ]) a0 | |||
in let | |||
trans : (A : Type) (a b c : A) | |||
-> Path (\i -> A) a b | |||
-> Path (\i -> A) b c | |||
-> Path (\i -> A) a c | |||
= \A a b c p q i -> | |||
comp (\j -> A) (i || ~i) | |||
(\j -> [ ~i -> a, i -> q j ]) | |||
(p i) | |||
in let | |||
elimI : (P : I -> Type) | |||
(a : P i0) | |||
(b : P i1) | |||
-> Path P a b | |||
-> (i : I) -> P i | |||
= \P a b p i -> p i | |||
in let | |||
contrI : (i : I) -> Path (\i -> I) i0 i | |||
= \i -> elimI (\x -> Path (\i -> I) i0 x) (\i -> i0) (\i -> i) (\i j -> i && j) i | |||
in let | |||
IisContr : (i : I) * ((j : I) -> Path (\i -> I) i j) | |||
= (i0, contrI) | |||
in IisContr |