Skip to content

Instantly share code, notes, and snippets.

@kik
Last active December 25, 2015 23:09
Show Gist options
  • Select an option

  • Save kik/7054648 to your computer and use it in GitHub Desktop.

Select an option

Save kik/7054648 to your computer and use it in GitHub Desktop.
おもちゃ証明器 僕の証明器はEckmann-Hiltonの定理が証明できる!2次のホモトピー群は可換群だ! Proof term は全然読めなくなってきた。
*Main> initGlobal >>= mod_eq
...
---- Proof ----
fun A : Type UnivVar "eq" => fun a : A => fun alpha beta : eq_refl A a = eq_refl A a :> a = a :> A => $eq_trans (eq_refl A a = eq_refl A a :> a = a :> A) ($eq_trans (a = a :> A) (eq_refl A a) (eq_refl A a) (eq_refl A a) alpha beta) ($eq_trans (a = a :> A) (eq_refl A a) (eq_refl A a) (eq_refl A a) alpha ($whisker_l A a a a (eq_refl A a) (eq_refl A a) (eq_refl A a) beta)) ($eq_trans (a = a :> A) (eq_refl A a) (eq_refl A a) (eq_refl A a) beta alpha) (eq_ind (fun t t' : eq_refl A a = eq_refl A a :> a = a :> A => fun _ : t = t' :> eq_refl A a = eq_refl A a :> a = a :> A => $eq_trans (a = a :> A) (eq_refl A a) (eq_refl A a) (eq_refl A a) alpha t = $eq_trans (a = a :> A) (eq_refl A a) (eq_refl A a) (eq_refl A a) alpha t' :> eq_refl A a = eq_refl A a :> a = a :> A) (fun t : eq_refl A a = eq_refl A a :> a = a :> A => eq_refl (eq_refl A a = eq_refl A a :> a = a :> A) ($eq_trans (a = a :> A) (eq_refl A a) (eq_refl A a) (eq_refl A a) alpha t)) beta ($whisker_l A a a a (eq_refl A a) (eq_refl A a) (eq_refl A a) beta) ($whisker_l_refl A a beta)) ($eq_trans (eq_refl A a = eq_refl A a :> a = a :> A) ($eq_trans (a = a :> A) (eq_refl A a) (eq_refl A a) (eq_refl A a) alpha ($whisker_l A a a a (eq_refl A a) (eq_refl A a) (eq_refl A a) beta)) ($eq_trans (a = a :> A) (eq_refl A a) (eq_refl A a) (eq_refl A a) ($whisker_r A a a a (eq_refl A a) (eq_refl A a) (eq_refl A a) alpha) ($whisker_l A a a a (eq_refl A a) (eq_refl A a) (eq_refl A a) beta)) ($eq_trans (a = a :> A) (eq_refl A a) (eq_refl A a) (eq_refl A a) beta alpha) (eq_ind (fun t t' : eq_refl A a = eq_refl A a :> a = a :> A -> eq_refl A a = eq_refl A a :> a = a :> A => fun _ : t = t' :> eq_refl A a = eq_refl A a :> a = a :> A -> eq_refl A a = eq_refl A a :> a = a :> A => t ($whisker_l A a a a (eq_refl A a) (eq_refl A a) (eq_refl A a) beta) = t' ($whisker_l A a a a (eq_refl A a) (eq_refl A a) (eq_refl A a) beta) :> eq_refl A a = eq_refl A a :> a = a :> A) (fun t : eq_refl A a = eq_refl A a :> a = a :> A -> eq_refl A a = eq_refl A a :> a = a :> A => eq_refl (eq_refl A a = eq_refl A a :> a = a :> A) (t ($whisker_l A a a a (eq_refl A a) (eq_refl A a) (eq_refl A a) beta))) ($eq_trans (a = a :> A) (eq_refl A a) (eq_refl A a) (eq_refl A a) alpha) ($eq_trans (a = a :> A) (eq_refl A a) (eq_refl A a) (eq_refl A a) ($whisker_r A a a a (eq_refl A a) (eq_refl A a) (eq_refl A a) alpha)) (eq_ind (fun t t' : eq_refl A a = eq_refl A a :> a = a :> A => fun _ : t = t' :> eq_refl A a = eq_refl A a :> a = a :> A => $eq_trans (a = a :> A) (eq_refl A a) (eq_refl A a) (eq_refl A a) t = $eq_trans (a = a :> A) (eq_refl A a) (eq_refl A a) (eq_refl A a) t' :> eq_refl A a = eq_refl A a :> a = a :> A -> eq_refl A a = eq_refl A a :> a = a :> A) (fun t : eq_refl A a = eq_refl A a :> a = a :> A => eq_refl (eq_refl A a = eq_refl A a :> a = a :> A -> eq_refl A a = eq_refl A a :> a = a :> A) ($eq_trans (a = a :> A) (eq_refl A a) (eq_refl A a) (eq_refl A a) t)) alpha ($whisker_r A a a a (eq_refl A a) (eq_refl A a) (eq_refl A a) alpha) ($whisker_r_refl A a alpha))) ($eq_trans (eq_refl A a = eq_refl A a :> a = a :> A) ($eq_trans (a = a :> A) (eq_refl A a) (eq_refl A a) (eq_refl A a) ($whisker_r A a a a (eq_refl A a) (eq_refl A a) (eq_refl A a) alpha) ($whisker_l A a a a (eq_refl A a) (eq_refl A a) (eq_refl A a) beta)) ($eq_trans (a = a :> A) (eq_refl A a) (eq_refl A a) (eq_refl A a) ($whisker_l A a a a (eq_refl A a) (eq_refl A a) (eq_refl A a) beta) ($whisker_r A a a a (eq_refl A a) (eq_refl A a) (eq_refl A a) alpha)) ($eq_trans (a = a :> A) (eq_refl A a) (eq_refl A a) (eq_refl A a) beta alpha) ($whisker_rl_lr A a a a (eq_refl A a) (eq_refl A a) alpha (eq_refl A a) (eq_refl A a) beta) ($eq_trans (eq_refl A a = eq_refl A a :> a = a :> A) ($eq_trans (a = a :> A) (eq_refl A a) (eq_refl A a) (eq_refl A a) ($whisker_l A a a a (eq_refl A a) (eq_refl A a) (eq_refl A a) beta) ($whisker_r A a a a (eq_refl A a) (eq_refl A a) (eq_refl A a) alpha)) ($eq_trans (a = a :> A) (eq_refl A a) (eq_refl A a) (eq_refl A a) ($whisker_l A a a a (eq_refl A a) (eq_refl A a) (eq_refl A a) beta) alpha) ($eq_trans (a = a :> A) (eq_refl A a) (eq_refl A a) (eq_refl A a) beta alpha) (eq_ind (fun t t' : $eq_trans A a a a (eq_refl A a) (eq_refl A a) = $eq_trans A a a a (eq_refl A a) (eq_refl A a) :> a = a :> A => fun _ : t = t' :> $eq_trans A a a a (eq_refl A a) (eq_refl A a) = $eq_trans A a a a (eq_refl A a) (eq_refl A a) :> a = a :> A => $eq_trans (a = a :> A) (eq_refl A a) (eq_refl A a) (eq_refl A a) ($whisker_l A a a a (eq_refl A a) (eq_refl A a) (eq_refl A a) beta) t = $eq_trans (a = a :> A) (eq_refl A a) (eq_refl A a) (eq_refl A a) ($whisker_l A a a a (eq_refl A a) (eq_refl A a) (eq_refl A a) beta) t' :> eq_refl A a = eq_refl A a :> a = a :> A) (fun t : $eq_trans A a a a (eq_refl A a) (eq_refl A a) = $eq_trans A a a a (eq_refl A a) (eq_refl A a) :> a = a :> A => eq_refl (eq_refl A a = eq_refl A a :> a = a :> A) ($eq_trans (a = a :> A) (eq_refl A a) (eq_refl A a) (eq_refl A a) ($whisker_l A a a a (eq_refl A a) (eq_refl A a) (eq_refl A a) beta) t)) ($whisker_r A a a a (eq_refl A a) (eq_refl A a) (eq_refl A a) alpha) alpha ($eq_sym ($eq_trans A a a a (eq_refl A a) (eq_refl A a) = $eq_trans A a a a (eq_refl A a) (eq_refl A a) :> a = a :> A) alpha ($whisker_r A a a a (eq_refl A a) (eq_refl A a) (eq_refl A a) alpha) ($whisker_r_refl A a alpha))) (eq_ind (fun t t' : eq_refl A a = eq_refl A a :> a = a :> A -> eq_refl A a = eq_refl A a :> a = a :> A => fun _ : t = t' :> eq_refl A a = eq_refl A a :> a = a :> A -> eq_refl A a = eq_refl A a :> a = a :> A => t alpha = t' alpha :> eq_refl A a = eq_refl A a :> a = a :> A) (fun t : eq_refl A a = eq_refl A a :> a = a :> A -> eq_refl A a = eq_refl A a :> a = a :> A => eq_refl (eq_refl A a = eq_refl A a :> a = a :> A) (t alpha)) ($eq_trans (a = a :> A) (eq_refl A a) (eq_refl A a) (eq_refl A a) ($whisker_l A a a a (eq_refl A a) (eq_refl A a) (eq_refl A a) beta)) ($eq_trans (a = a :> A) (eq_refl A a) (eq_refl A a) (eq_refl A a) beta) (eq_ind (fun t t' : $eq_trans A a a a (eq_refl A a) (eq_refl A a) = $eq_trans A a a a (eq_refl A a) (eq_refl A a) :> a = a :> A => fun _ : t = t' :> $eq_trans A a a a (eq_refl A a) (eq_refl A a) = $eq_trans A a a a (eq_refl A a) (eq_refl A a) :> a = a :> A => $eq_trans (a = a :> A) (eq_refl A a) (eq_refl A a) (eq_refl A a) t = $eq_trans (a = a :> A) (eq_refl A a) (eq_refl A a) (eq_refl A a) t' :> eq_refl A a = eq_refl A a :> a = a :> A -> eq_refl A a = eq_refl A a :> a = a :> A) (fun t : $eq_trans A a a a (eq_refl A a) (eq_refl A a) = $eq_trans A a a a (eq_refl A a) (eq_refl A a) :> a = a :> A => eq_refl (eq_refl A a = eq_refl A a :> a = a :> A -> eq_refl A a = eq_refl A a :> a = a :> A) ($eq_trans (a = a :> A) (eq_refl A a) (eq_refl A a) (eq_refl A a) t)) ($whisker_l A a a a (eq_refl A a) (eq_refl A a) (eq_refl A a) beta) beta ($eq_sym ($eq_trans A a a a (eq_refl A a) (eq_refl A a) = $eq_trans A a a a (eq_refl A a) (eq_refl A a) :> a = a :> A) beta ($whisker_l A a a a (eq_refl A a) (eq_refl A a) (eq_refl A a) beta) ($whisker_l_refl A a beta)))))))
Eckmann_Hilton is defined.
*Main>
{-# LANGUAGE TupleSections #-}
import Data.List
import Data.Maybe
import Data.IORef
import Control.Applicative
import Control.Exception hiding (try, assert)
import Control.Monad.State
import Control.Monad.Reader
import Control.Monad.Error
import Control.Monad.Writer
import Text.Parsec hiding ((<|>))
data Univ = Univ0
| UnivLift Univ Int
| UnivMax Univ Univ
| UnivVar String
deriving (Eq, Show)
data Term = TmU Univ
| TmVar Int
| TmConst String
| TmHole Int
| TmProd (Maybe String) Type Term
| TmAbs (Maybe String) Type Term
| TmApp Term Term
| TmEq Type Term Term
| TmRefl Type Term
| TmEqInd Type Term Term Term Term
type TermParser a = Parsec String () a
termParser :: [Maybe String] -> TermParser Term
termParser env = do { t <- goExpr env; eof; return t }
where
ident = try $ do { spaces
; lookAhead $ letter <|> char '_'
; many1 $ alphaNum <|> oneOf "_'"
}
op s = try $ ops >>= \x -> if s == x then return () else mzero
ops = do { spaces
; choice $ map (try . string) ["->", "=>", ":>", "(", ")", ",", ":", "="]
}
binder e body = binders [] e body <|> binder1 e body
binder1 e body = do { names <- many1 ident
; op ":"
; ty <- goExpr e
; let bs = [(name, termShift i ty) | (i, name) <- zip [0..] names]
e' = foldl (\x y -> Just y : x) e names
; body bs e'
}
binders bs e body = do { op "("
; binder1 e $ \bs' e' -> do { op ")"
; binders (bs++bs') e' body
<|> body (bs++bs') e'
}
}
goExpr e = go10
where
go10 = go4
go4 = go3 `chainr1` do { op "->"; return $ \x y -> TmProd Nothing x (termShift 1 y) }
go3 = do { x <- go2
; option x $ do { op "="
; y <- go2
; op ":>"
; a <- go3
; return $ TmEq a x y
}
}
go2 = many1 (try go1) >>= return . foldl1 TmApp
go1 = do { v <- ident; goIdent v }
<|> do { between (op "(") (op ")") go10 }
goIdent "Type0" = return $ TmU Univ0
goIdent "Type" = do { name <- ident; return $ TmU (UnivVar name) }
goIdent "forall" = binder e $ \bs e' -> do { op ","
; body <- goExpr e'
; return $ foldr (\(name, ty) b -> TmProd (Just name) ty b) body bs
}
goIdent "fun" = binder e $ \bs e' -> do { op "=>"
; body <- goExpr e'
; return $ foldr (\(name, ty) b -> TmAbs (Just name) ty b) body bs
}
goIdent "eq_refl" = TmRefl <$> go1 <*> go1
goIdent "eq_ind" = TmEqInd <$> go1 <*> go1 <*> go1 <*> go1 <*> go1
goIdent n = case elemIndex (Just n) e of
Just i -> return $ TmVar i
Nothing -> return $ TmConst n
showsTerm :: Local -> Term -> ShowS
showsTerm l = walk 10 $ env l
where
env l = foldr (\(n, _) e -> alpha e n:e) [] l
alpha e n = newName e $ maybe "t" id n
newName e n = if elem n e then newName e $ n ++ "'" else n
walk pr e t = case t of
TmU i -> showString "Type " . shows i
TmVar i | i < length e -> showString $ e!!i
| otherwise -> showString "_var_" . shows i
TmConst n -> showString "$" . showString n
TmHole i -> showString "_" . shows i
TmProd n ty body | not (termUse 0 body) ->
paren 4 $ walk 3 e ty . showString " -> " . walk 4 ("_":e) body
TmProd _ _ _ ->
paren 2 $ showString "forall " . prod e t
where
prod e (TmProd n ty t@(TmProd _ ty' body))
| termUse 0 body && termShift 1 ty == ty' =
showString n' . showString " " . prod (n':e) t
where n' = alpha e n
prod e (TmProd n ty body) =
showString n' . showString " : " . walk 10 e ty . showString ", " . walk 10 (n':e) body
where n' = alpha e n
prod _ _ = undefined
TmAbs _ _ _ ->
paren 2 $ showString "fun " . abs e t
where
abs e (TmAbs n ty t@(TmAbs _ ty' body))
| termShift 1 ty == ty' =
showString n' . showString " " . abs (n':e) t
where n' = if termUse 0 t then alpha e n else "_"
abs e (TmAbs n ty body) =
showString n' . showString " : " . walk 10 e ty . showString " => " . walk 10 (n':e) body
where n' = if termUse 0 body then alpha e n else "_"
TmApp t1 t2 -> paren 2 $ list [w 2 t1, w 1 t2]
TmRefl a x -> paren 2 $ list [showString "eq_refl", w 1 a, w 1 x]
TmEqInd ct c x y p -> paren 2 $ list $ showString "eq_ind" : map (w 1) [ct, c, x, y, p]
TmEq a x y -> paren 3 $ list[w 2 x, showString "=", w 2 y, showString ":>", w 3 a]
where
w pr = walk pr e
paren n s = showParen (pr < n) s
list = foldr (.) id . intersperse (showChar ' ')
instance Show Term where
showsPrec _ t = showsTerm [] t
instance Eq Term where
TmU i == TmU j = i == j
TmVar i == TmVar j = i == j
TmConst i == TmConst j = i == j
TmHole i == TmHole j = i == j
TmProd _ t1 t2 == TmProd _ s1 s2 = t1 == s1 && t2 == s2
TmAbs _ t1 t2 == TmAbs _ s1 s2 = t1 == s1 && t2 == s2
TmApp t1 t2 == TmApp s1 s2 = t1 == s1 && t2 == s2
TmEq t1 t2 t3 == TmEq s1 s2 s3 = t1 == s1 && t2 == s2 && t3 == s3
TmRefl t1 t2 == TmRefl s1 s2 = t1 == s1 && t2 == s2
TmEqInd t1 t2 t3 t4 t5 == TmEqInd s1 s2 s3 s4 s5 =
t1 == s1 && t2 == s2 && t3 == s3 && t4 == s4 && t5 == s5
_ == _ = False
type Type = Term
data Binding = Decl Type
| Def Type Term
deriving (Show, Eq)
type UnivBindings = [(String, Univ)]
type Local = [(Maybe String, Binding)]
type GlobalBindings = [(String, Binding)]
data Global = Global { gbindings :: GlobalBindings
, ubindings :: UnivBindings
}
deriving (Show)
data TermError = TypeError String
deriving (Show)
instance Error TermError where
strMsg = TypeError
type ReadGlobal a = Reader Global a
type TermHandler a = ErrorT TermError (Reader Global) a
typeError :: String -> TermHandler a
typeError = throwError . TypeError
lookupVar :: Local -> Int -> TermHandler (Maybe String, Binding)
lookupVar env i = if null bs then err else return $ head bs
where
bs = drop i env
err = typeError $ "unbound variable: " ++ show i
lookupConst :: String -> TermHandler Binding
lookupConst n = do
g <- ask
case lookup n (gbindings g) of
Just b -> return b
Nothing -> typeError $ "unbound constant: " ++ show n
termShift :: Int -> Term -> Term
termShift d = walk 0
where
walk :: Int -> Term -> Term
walk c t = case t of
TmU _ -> t
TmVar i | i >= c -> TmVar $ i + d
| otherwise -> t
TmConst _ -> t
TmHole _ -> error "unable to shift hole"
TmProd n ty body -> TmProd n (w id ty) (w (+1) body)
TmAbs n ty body -> TmAbs n (w id ty) (w (+1) body)
TmApp t1 t2 -> TmApp (w id t1) (w id t2)
TmEq t1 t2 t3 -> TmEq (w id t1) (w id t2) (w id t3)
TmRefl t1 t2 -> TmRefl (w id t1) (w id t2)
TmEqInd ct a x y p ->
TmEqInd (w id ct) (w id a) (w id x) (w id y) (w id p)
where
w f = walk $ f c
termSubst :: Int -> Term -> Term -> Term
termSubst j s = walk 0
where
walk :: Int -> Term -> Term
walk c t = case t of
TmU _ -> t
TmVar i | i == j + c -> termShift c s
| otherwise -> t
TmConst _ -> t
TmHole _ -> error "unable to subst hole"
TmProd n ty body -> TmProd n (w id ty) (w (+1) body)
TmAbs n ty body -> TmAbs n (w id ty) (w (+1) body)
TmApp t1 t2 -> TmApp (w id t1) (w id t2)
TmEq t1 t2 t3 -> TmEq (w id t1) (w id t2) (w id t3)
TmRefl t1 t2 -> TmRefl (w id t1) (w id t2)
TmEqInd ct a x y p ->
TmEqInd (w id ct) (w id a) (w id x) (w id y) (w id p)
where
w f = walk $ f c
-- [s/0]t
subst :: Term -> Term -> Term
subst s t = termShift (-1) $ termSubst 0 (termShift 1 s) t
termPattern :: Int -> Term -> Term -> Term
termPattern i s = walk 0 s
where
walk c s t | s == t = TmVar $ i + c
walk c s t = case t of
TmProd n ty body -> TmProd n (w id ty) (w (+1) body)
TmAbs n ty body -> TmAbs n (w id ty) (w (+1) body)
TmApp t1 t2 -> TmApp (w id t1) (w id t2)
TmEq t1 t2 t3 -> TmEq (w id t1) (w id t2) (w id t3)
TmRefl t1 t2 -> TmRefl (w id t1) (w id t2)
TmEqInd ct a x y p ->
TmEqInd (w id ct) (w id a) (w id x) (w id y) (w id p)
_ -> t
where
w f = walk (f c) (termShift (f 0) s)
-- pattern s t = t' where [s/0]t' = t
pattern :: Term -> Term -> Term
pattern s t = termPattern 0 (termShift 1 s) (termShift 1 t)
termUse :: Int -> Term -> Bool
termUse j = walk 0
where
walk c t = case t of
TmVar i | i == j + c -> True
| otherwise -> False
TmProd n ty body -> w id ty || w (+1) body
TmAbs n ty body -> w id ty || w (+1) body
TmApp t1 t2 -> w id t1 || w id t2
TmEq t1 t2 t3 -> w id t1 || w id t2 || w id t3
TmRefl t1 t2 -> w id t1 || w id t2
TmEqInd ct a x y p -> or [w id ct, w id a, w id x, w id y, w id p]
_ -> False
where
w f = walk (f c)
reduceValue :: Local -> Term -> TermHandler Term
reduceValue e = rd
where
rd t = case t of
TmU _ -> return t
TmVar v -> do (_, b) <- lookupVar e v
case b of
Def _ t' -> return $ termShift (v+1) t'
_ -> return t
TmConst n -> do b <- lookupConst n
case b of
Def _ t' -> return t'
_ -> return t
TmHole _ -> error "reducing Hole"
TmProd n ty body -> TmProd n <$> rd ty <*> rd' ((n, Decl ty):) body
TmAbs n ty body -> TmAbs n <$> rd ty <*> rd' ((n, Decl ty):) body
TmApp t1 t2 -> do t1' <- rd t1
t2' <- rd t2
case t1' of
TmAbs n ty body ->
termShift (-1) <$> rd' ((n, Def ty t2'):) body
_ -> return $ TmApp t1' t2'
TmEq a x y -> TmEq <$> (rd a) <*> (rd x) <*> (rd y)
TmRefl a x -> TmRefl <$> (rd a) <*> (rd x)
TmEqInd ct c x y p -> do p' <- rd p
case p' of
TmRefl a z -> rd $ (TmApp c x)
_ -> TmEqInd <$> rd ct <*> rd c <*> rd x <*> rd y <*> pure p'
rd' f t = reduceValue (f e) t
univLe :: Univ -> Univ -> TermHandler Bool
univLe = go 0
where
go n Univ0 Univ0 | n >= 0 = return True
go n (UnivVar v1) (UnivVar v2) | n >= 0 && v1 == v2 = return True
go n (UnivMax u v) w =
(&&) <$> go n u w <*> go n v w
go n (UnivLift u i) v = go (n - i) u v
go n u (UnivLift v i) = go (n + i) u v
go n u (UnivVar v) = do g <- ask
case lookup v (ubindings g) of
Nothing -> typeError $ "not declared universe: " ++ v
Just w -> go n u w
go n u (UnivMax v w) =
(||) <$> go n u v <*> go n u w
go _ _ _ = return False
univEq :: Univ -> Univ -> TermHandler Bool
univEq u1 u2 = (&&) <$> univLe u1 u2 <*> univLe u2 u1
-- e |- t1 <: t2
convertible :: Local -> Term -> Term -> TermHandler Bool
convertible e t1 t2 = do t1' <- reduceValue e t1
t2' <- reduceValue e t2
go False t1' t2'
where
go _ s1 s2 | s1 == s2 = return True
go True (TmU u1) (TmU u2) = univEq u1 u2
go False (TmU u1) (TmU u2) = univLe u1 u2
go e (TmProd _ ty1 body1) (TmProd _ ty2 body2) =
ands [go True ty1 ty2, go e body1 body2]
go e (TmAbs _ ty1 body1) (TmAbs _ ty2 body2) =
ands [go True ty1 ty2, go e body1 body2]
go e (TmApp f1 a1) (TmApp f2 a2) =
ands [go e f1 f2, go True a1 a2]
go _ (TmEq a1 x1 y1) (TmEq a2 x2 y2) =
ands [go True a1 a2, go True x1 x2, go True y1 y2]
go _ (TmRefl a1 x1) (TmRefl a2 x2) =
ands [go True a1 a2, go True x1 x2]
go _ (TmEqInd ct1 c1 x1 y1 p1) (TmEqInd ct2 c2 x2 y2 p2) =
ands [go True ct1 ct2, go True c1 c2, go True x1 x2, go True y1 y2, go True p1 p2]
go _ _ _ = return False
ands = fmap and . sequence
typeofBinding :: Binding -> Type
typeofBinding (Decl ty) = ty
typeofBinding (Def ty _) = ty
reduceToUniverse :: Local -> Term -> TermHandler Univ
reduceToUniverse e t = reduceValue e t >>= go
where go (TmU i) = return i
go t' = typeError $ "not universe: " ++ showsTerm e t' ""
assertUniverse :: Local -> Term -> TermHandler ()
assertUniverse e t = void $ reduceToUniverse e t
typeofType :: Local -> Term -> TermHandler Univ
typeofType e t = reduceToUniverse e =<< typeof e t
assertType :: Local -> Term -> TermHandler ()
assertType e t = void $ typeofType e t
univOfProd :: Univ -> Univ -> TermHandler Univ
univOfProd u1 u2 = return $ UnivMax u1 u2
univSucc :: Univ -> Univ
univSucc (UnivLift u i) = UnivLift u (i + 1)
univSucc (UnivMax u1 u2) = UnivMax (univSucc u1) (univSucc u2)
univSucc u = UnivLift u 1
-- e |- t : ty
typeCheck :: Local -> Term -> Term -> TermHandler ()
typeCheck e t ty = do tty <- typeof e t
b <- convertible e tty ty
unless b $ typeError $ "typecheck error: " ++ showsTerm e t "" ++ " : " ++ showsTerm e ty ""
typeof :: Local -> Term -> TermHandler Type
typeof e = to
where
to (TmU u) = return $ TmU $ univSucc u
to (TmVar v) = do (_, b) <- lookupVar e v
return $ termShift (v+1) $ typeofBinding b
to (TmConst n) = do b <- lookupConst n
return $ typeofBinding b
to (TmHole _) = error "typeof Hole"
to (TmProd n ty body) = do uty <- typeofType e ty
ubody <- typeofType ((n, Decl ty):e) body
TmU <$> (univOfProd uty ubody)
to (TmAbs n ty body) = do assertType e ty
tbody <- typeof ((n, Decl ty):e) body
return $ TmProd n ty tbody
to (TmApp t1 t2) = do tt1 <- to t1
case tt1 of
TmProd _ ty body -> do
typeCheck e t2 ty
return $ subst t2 body
_ -> error "not applicative"
to (TmEq a x y) = do ta <- to a
ua <- reduceToUniverse e ta
typeCheck e x a
typeCheck e y a
return $ TmU ua
to (TmRefl a x) = do assertType e a
typeCheck e x a
return $ TmEq a x x
to (TmEqInd ct c x y p) = do
a <- to x
typeCheck e x a
typeCheck e y a
typeCheck e p $ TmEq a x y
-- e, x:A, y:A, p:A |- ct x y p : U
let e' = map (Nothing,) [Decl (TmEq (termShift 2 a) (TmVar 1) (TmVar 0)), Decl (termShift 1 a), Decl (termShift 0 a)] ++ e
assertType e' (TmApp (TmApp (TmApp (termShift 3 ct) (TmVar 2)) (TmVar 1)) (TmVar 0))
-- e, z:A |- c z : ct z z (refl z)
let e'' = (Nothing, Decl a):e
let cz = TmApp (TmApp (TmApp (termShift 1 ct) (TmVar 0)) (TmVar 0)) (TmRefl (termShift 1 a) (TmVar 0))
typeCheck e'' (TmApp (termShift 1 c) (TmVar 0)) cz
-- ct x y p
return $ TmApp (TmApp (TmApp ct x) y) p
data Goal = Goal Int Type Local
deriving (Show)
data ProofState = ProofState { goals :: [Goal]
, proof :: Term
, lemmaName :: String
, mainGoal :: Term
, nextHoleId :: Int
}
deriving (Show)
data GlobalState = GlobalState Global (Maybe ProofState)
--deriving (Show)
printProofState :: ProofState -> IO ()
printProofState s = do mapM_ runGoal $ zip [1..] $ goals s
--runProof $ proof s
where
runGoal (i, (Goal _ ty e)) = do
putStrLn $ "---- Goal " ++ show i ++ " ----"
mapM_ runBinding $ zip [0..] $ tails e
putStrLn "===="
putStrLn $ showsTerm e ty ""
runProof p = do
putStrLn $ "---- Proof ----"
putStrLn $ showsTerm [] p ""
runBinding (i, ((n, Decl ty):e)) = do
putStrLn $ "[" ++ show i ++ "] " ++ name n ++ " : " ++ showsTerm e ty ""
runBinding (i, ((n, Def t ty):e)) = do
putStrLn $ "[" ++ show i ++ "] " ++ name n ++ " := " ++ showsTerm e t "" ++ " : " ++ showsTerm e ty ""
runBinding (_, []) = return ()
name (Just n) = n
name Nothing = "_"
initGlobal :: IO (IORef GlobalState)
initGlobal = newIORef $ GlobalState (Global { gbindings = [], ubindings = [] }) Nothing
type ProverCommand a = ReaderT (IORef GlobalState) IO a
type CommandImpl a = StateT GlobalState IO a
runTermHandler :: TermHandler a -> CommandImpl a
runTermHandler h = do GlobalState g _ <- get
case runReader (runErrorT h) g of
Right v -> return v
Left e -> fail $ show e
command :: CommandImpl () -> ProverCommand ()
command body = do
gs <- ask
lift $ catch (go gs) err
where
go s = readIORef s >>= execStateT body >>= writeIORef s
err :: IOException -> IO ()
err e = do
putStrLn $ "Error: " ++ show e
return ()
parseTerm :: String -> CommandImpl Term
parseTerm s = do GlobalState gs mps <- get
let e = case mps of
Just (ProofState { goals = Goal _ _ e :_ }) -> e
_ -> []
case runParser (termParser (map fst e)) () "" s of
Right t -> return t
Left err -> fail $ show err
uvar :: String -> Univ -> ProverCommand ()
uvar n u = command f
where f = do GlobalState g mps <- get
-- TODO: need check
let g' = g { ubindings = (n, u):ubindings g }
put $ GlobalState g' mps
lemma :: String -> String -> ProverCommand ()
lemma n props = command f
where f = do prop <- parseTerm props
GlobalState g mps <- get
unless (isNothing mps) $ fail "proof not complete"
runTermHandler $ assertType [] prop
liftIO $ printProofState (ps prop)
put $ GlobalState g (Just (ps prop))
ps prop = ProofState { goals = [Goal 0 prop []]
, proof = TmHole 0
, mainGoal = prop
, lemmaName = n
, nextHoleId = 1
}
qed :: ProverCommand ()
qed = command f
where f = do GlobalState g mps <- get
case mps of
Nothing -> fail "not in proof mode"
Just ps -> do
unless (null $ goals ps) $ fail "proof not complete"
ty <- runTermHandler $ typeof [] (proof ps)
b <- runTermHandler $ convertible [] ty (mainGoal ps)
unless b $ fail "invalid proof"
liftIO $ putStrLn $ lemmaName ps ++ " is defined."
put $ GlobalState (g { gbindings = (lemmaName ps, Def (mainGoal ps) (proof ps)):gbindings g }) Nothing
substHole :: Int -> Term -> Term -> Term
substHole i = subst
where
subst s = go
where
go t@(TmU _) = t
go t@(TmVar _) = t
go t@(TmConst _) = t
go t@(TmHole j) | i == j = s
| otherwise = t
go (TmProd n t1 t2) = TmProd n (go t1) (go t2)
go (TmAbs n t1 t2) = TmAbs n (go t1) (go t2)
go (TmApp t1 t2) = TmApp (go t1) (go t2)
go (TmEq t1 t2 t3) = TmEq (go t1) (go t2) (go t3)
go (TmRefl t1 t2) = TmRefl (go t1) (go t2)
go (TmEqInd ct a x y p) =
TmEqInd (go ct) (go a) (go x) (go y) (go p)
type TacImpl a = CommandImpl a
curGoal :: TacImpl Goal
curGoal = do
GlobalState _ s <- get
case s of
Just (ProofState { goals = g:_ }) -> return g
_ -> fail "no more goal"
updateGoal :: Int -> Term -> [Goal] -> TacImpl ()
updateGoal i pf ss = do
GlobalState g ps <- get
case ps of
Just s@(ProofState { goals = _:gs }) ->
put $ GlobalState g $ Just $ s { goals = ss ++ gs
, proof = substHole i pf (proof s)
}
_ -> fail "no more goal"
allocId :: TacImpl Int
allocId = do
GlobalState g ps <- get
case ps of
Just s -> do
let i = nextHoleId s
put $ GlobalState g $ Just $ s { nextHoleId = i + 1 }
return i
_ -> fail "not in proof mode"
tac :: TacImpl () -> ProverCommand ()
tac f = command body
where
body = do
f
GlobalState g ps <- get
case ps of
Just s -> lift $ printProofState s
Nothing -> return ()
exact :: String -> ProverCommand ()
exact ts = tac f
where
f = do
t <- parseTerm ts
Goal i g e <- curGoal
ty <- runTermHandler $ typeof e t
b <- runTermHandler $ convertible e ty g
unless b $ fail "invalid proof"
updateGoal i t []
assert :: String -> ProverCommand ()
assert ts = tac f
where
f = do
t <- parseTerm ts
Goal i g e <- curGoal
holeId1 <- allocId
holeId2 <- allocId
let goal1 = Goal holeId1 (TmProd Nothing t (termShift 1 g)) e
goal2 = Goal holeId2 t e
updateGoal i (TmApp (TmHole holeId1) (TmHole holeId2)) [goal1, goal2]
intros :: [String] -> ProverCommand ()
intros names = tac (f names)
where
f [] = return ()
f (name:ns) = do
Goal i g e <- curGoal
case g of
TmProd _ ty body -> do
holeId <- allocId
updateGoal i (TmAbs (Just name) ty (TmHole holeId)) [Goal holeId body ((Just name, Decl ty):e)]
f ns
_ -> fail "not product type"
introsw :: String -> ProverCommand ()
introsw names = intros $ words names
intro :: String -> ProverCommand ()
intro name = intros [name]
elim_eq :: String -> String -> ProverCommand ()
elim_eq name ts = tac f
where
f = do
p <- parseTerm ts
Goal i g e <- curGoal
ty <- runTermHandler $ reduceValue e =<< typeof e p
case ty of
TmEq a x y -> do
--liftIO $ putStrLn $ "eliminating: " ++ show p ++ " : " ++ show x ++ " = " ++ show y ++ " <: " ++ show a
let ct = pattern (termShift 2 p) $ pattern (termShift 1 y) $ pattern x g
--liftIO $ putStrLn $ "pattern: " ++ show ct
let cz = pattern (TmVar 0) $ subst (TmVar 0) $ subst (TmVar 1) $ subst (TmRefl (termShift 2 a) (TmVar 2)) ct
holeId <- allocId
updateGoal i (TmEqInd (TmAbs Nothing a (TmAbs Nothing (termShift 1 a) (TmAbs Nothing (TmEq (termShift 2 a) (TmVar 1) (TmVar 0)) ct)))
(TmAbs (Just name) a (TmHole holeId)) x y p) [Goal holeId cz ((Just name, Decl a):e)]
_ ->
fail "not eq type"
trans :: String -> ProverCommand ()
trans s = tac f
where
f = do
t <- parseTerm s
Goal i g e <- curGoal
case g of
TmEq a x y -> do
h1 <- allocId
h2 <- allocId
let g1 = TmEq a x t
g2 = TmEq a t y
updateGoal i (foldl1 TmApp [TmConst "eq_trans", a, x, t, y, TmHole h1, TmHole h2])
[Goal h1 g1 e, Goal h2 g2 e]
_ -> fail "not identity type"
sym :: ProverCommand ()
sym = do tac f
where
f = do
Goal i g e <- curGoal
case g of
TmEq a x y -> do
h1 <- allocId
let g1 = TmEq a y x
updateGoal i (foldl1 TmApp [TmConst "eq_sym", a, y, x, TmHole h1])
[Goal h1 g1 e]
_ -> fail "not identity type"
f_equal_1 :: ProverCommand ()
f_equal_1 = do tac f
where
f = do
Goal i g e <- curGoal
case g of
TmEq a (TmApp f x) (TmApp g y) | x == y -> do
h1 <- allocId
a <- runTermHandler $ typeof e f
b <- runTermHandler $ typeof e (TmApp f x)
let g1 = TmEq a f g
ct = TmAbs Nothing a (TmAbs Nothing (termShift 1 a) (TmAbs Nothing (TmEq (termShift 2 a) (TmVar 1) (TmVar 0))
(TmEq (termShift 3 b)
(TmApp (TmVar 2) (termShift 3 x))
(TmApp (TmVar 1) (termShift 3 x)))))
c = TmAbs Nothing a (TmRefl (termShift 1 b) (TmApp (TmVar 0) (termShift 1 x)))
updateGoal i (TmEqInd ct c f g (TmHole h1)) [Goal h1 g1 e]
_ -> fail "not identity type"
f_equal_2 :: ProverCommand ()
f_equal_2 = do tac f
where
f = do
Goal i g e <- curGoal
case g of
TmEq a (TmApp f x) (TmApp g y) | f == g -> do
h1 <- allocId
a <- runTermHandler $ typeof e x
b <- runTermHandler $ typeof e (TmApp f x)
let g1 = TmEq a x y
ct = TmAbs Nothing a (TmAbs Nothing (termShift 1 a) (TmAbs Nothing (TmEq (termShift 2 a) (TmVar 1) (TmVar 0))
(TmEq (termShift 3 b)
(TmApp (termShift 3 f) (TmVar 2))
(TmApp (termShift 3 f) (TmVar 1)))))
c = TmAbs Nothing a (TmRefl (termShift 1 b) (TmApp (termShift 1 f) (TmVar 0)))
updateGoal i (TmEqInd ct c x y (TmHole h1)) [Goal h1 g1 e]
_ -> fail "not identity type"
compute :: String -> ProverCommand ()
compute s = command f
where
f = do t <- parseTerm s
GlobalState g mps <- get
case mps of
Nothing -> do
v <- runTermHandler $ reduceValue [] t -- TODO: type check
liftIO $ putStrLn $ "Value: " ++ show v
Just (ProofState { goals = Goal _ _ e:_ }) -> do
v <- runTermHandler $ reduceValue e t -- TODO: type check
liftIO $ putStrLn $ "Value: " ++ show v
mod_eq :: IORef GlobalState -> IO ()
mod_eq g = flip runReaderT g $ do
uvar "eq" Univ0
lemma "eq_sym" "forall (A : Type eq) (x y : A), x = y :> A -> y = x :> A"
introsw "A x y p"
elim_eq "x'" "p"
exact "eq_refl A x'"
qed
compute "fun A : Type eq => fun x : A => eq_sym A x x (eq_refl A x)"
lemma "eq_trans" "forall (A : Type eq) (x y z : A), x = y :> A -> y = z :> A -> x = z :> A"
introsw "A x y z p"
elim_eq "x'" "p"
intro "q"
elim_eq "y'" "q"
exact "eq_refl A y'"
qed
compute "fun A : Type eq => fun x : A => eq_trans A x x x (eq_refl A x) (eq_refl A x)"
lemma "path_o_refl" "forall (A : Type eq) (x y : A) (p : x = y :> A), p = eq_trans A x y y p (eq_refl A y) :> (x = y :> A)"
introsw "A x y p"
elim_eq "x'" "p"
exact "eq_refl (x' = x' :> A) (eq_refl A x')"
qed
lemma "refl_o_path" "forall (A : Type eq) (x y : A) (p : x = y :> A), p = eq_trans A x x y (eq_refl A x) p :> (x = y :> A)"
introsw "A x y p"
elim_eq "x'" "p"
exact "eq_refl (x' = x' :> A) (eq_refl A x')"
qed
lemma "inv_o_path" "forall (A : Type eq) (x y : A) (p : x = y :> A), eq_trans A y x y (eq_sym A x y p) p = eq_refl A y :> (y = y :> A)"
introsw "A x y p"
elim_eq "x'" "p"
exact "eq_refl (x' = x' :> A) (eq_refl A x')"
qed
lemma "path_o_inv" "forall (A : Type eq) (x y : A) (p : x = y :> A), eq_trans A x y x p (eq_sym A x y p) = eq_refl A x :> (x = x :> A)"
introsw "A x y p"
elim_eq "x'" "p"
exact "eq_refl (x' = x' :> A) (eq_refl A x')"
qed
lemma "inv_inv" "forall (A : Type eq) (x y : A) (p : x = y :> A), eq_sym A y x (eq_sym A x y p) = p :> (x = y :> A)"
introsw "A x y p"
elim_eq "x'" "p"
exact "eq_refl (x' = x' :> A) (eq_refl A x')"
qed
lemma "o_assoc" "forall (A : Type eq) (x y z w : A) (p : x = y :> A) (q : y = z :> A) (r : z = w :> A), eq_trans A x y w p (eq_trans A y z w q r) = eq_trans A x z w (eq_trans A x y z p q) r :> (x = w :> A)"
introsw "A x y z w p"
elim_eq "x'" "p"
intro "q"
elim_eq "y'" "q"
intro "r"
elim_eq "z'" "r"
exact "eq_refl (z' = z' :> A) (eq_refl A z')"
qed
lemma
"whisker_r"
("forall (A : Type eq) (a b c : A) (r : b = c :> A) (p q : a = b :> A) (alpha : p = q :> a = b :> A), "
++ "eq_trans A a b c p r = eq_trans A a b c q r :> a = c :> A")
introsw "A a b c r"
elim_eq "x" "r"
introsw "p q alpha"
trans "q"
trans "p"
sym
exact "path_o_refl A a x p"
exact "alpha"
exact "path_o_refl A a x q"
qed
lemma
"whisker_l"
("forall (A : Type eq) (a b c : A) (q : a = b :> A) (r s : b = c :> A) (beta : r = s :> b = c :> A), "
++ "eq_trans A a b c q r = eq_trans A a b c q s :> a = c :> A")
introsw "A a b c q"
elim_eq "x" "q"
introsw "r s beta"
trans "s"
trans "r"
sym
exact "refl_o_path A x c r"
exact "beta"
exact "refl_o_path A x c s"
qed
lemma
"whisker_r_refl"
("forall (A : Type eq) (a : A) (alpha : eq_refl A a = eq_refl A a :> a = a :> A), "
++ "alpha = whisker_r A a a a (eq_refl A a) (eq_refl A a) (eq_refl A a) alpha :> eq_refl A a = eq_refl A a :> a = a :> A")
introsw "A a alpha"
trans "eq_trans (a = a :> A) (eq_refl A a) (eq_refl A a) (eq_refl A a) (eq_refl (a = a :> A) (eq_refl A a)) alpha"
exact "refl_o_path (a = a :> A) (eq_refl A a) (eq_refl A a) alpha"
exact "path_o_refl (a = a :> A) (eq_refl A a) (eq_refl A a) (eq_trans (a = a :> A) (eq_refl A a) (eq_refl A a) (eq_refl A a) (eq_refl (a = a :> A) (eq_refl A a)) alpha)"
qed
lemma
"whisker_l_refl"
("forall (A : Type eq) (a : A) (beta : eq_refl A a = eq_refl A a :> a = a :> A), "
++ "beta = whisker_l A a a a (eq_refl A a) (eq_refl A a) (eq_refl A a) beta :> eq_refl A a = eq_refl A a :> a = a :> A")
introsw "A a beta"
trans "eq_trans (a = a :> A) (eq_refl A a) (eq_refl A a) (eq_refl A a) (eq_refl (a = a :> A) (eq_refl A a)) beta"
exact "refl_o_path (a = a :> A) (eq_refl A a) (eq_refl A a) beta"
exact "path_o_refl (a = a :> A) (eq_refl A a) (eq_refl A a) (eq_trans (a = a :> A) (eq_refl A a) (eq_refl A a) (eq_refl A a) (eq_refl (a = a :> A) (eq_refl A a)) beta)"
qed
lemma
"whisker_rl_lr"
("forall (A : Type eq) (a b c : A) (p q : a = b :> A) (alpha : p = q :> a = b :> A) "
++ "(r s : b = c :> A) (beta : r = s :> b = c :> A), "
++ "eq_trans (a = c :> A) "
++ "(eq_trans A a b c p r) "
++ "(eq_trans A a b c q r) "
++ "(eq_trans A a b c q s) "
++ "(whisker_r A a b c r p q alpha) (whisker_l A a b c q r s beta) ="
++ "eq_trans (a = c :> A) "
++ "(eq_trans A a b c p r) "
++ "(eq_trans A a b c p s) "
++ "(eq_trans A a b c q s) "
++ "(whisker_l A a b c p r s beta) (whisker_r A a b c s p q alpha) "
++ ":> eq_trans A a b c p r = eq_trans A a b c q s :> a = c :> A")
introsw "A a b c p q alpha"
elim_eq "p'" "alpha"
elim_eq "a'" "p'"
introsw "r s beta"
elim_eq "r'" "beta"
elim_eq "b'" "r'"
exact "eq_refl (eq_refl A b' = eq_refl A b' :> b' = b' :> A) (eq_refl (b' = b' :> A) (eq_refl A b'))"
qed
lemma "Eckmann_Hilton"
("forall (A : Type eq) (a : A) "
++ "(alpha : eq_refl A a = eq_refl A a :> a = a :> A)"
++ "(beta : eq_refl A a = eq_refl A a :> a = a :> A), "
++ "eq_trans (a = a :> A) (eq_refl A a) (eq_refl A a) (eq_refl A a) alpha beta = "
++ "eq_trans (a = a :> A) (eq_refl A a) (eq_refl A a) (eq_refl A a) beta alpha :> eq_refl A a = eq_refl A a :> a = a :> A")
introsw "A a alpha beta"
trans ("eq_trans (a = a :> A) (eq_refl A a) (eq_refl A a) (eq_refl A a) alpha "
++ "(whisker_l A a a a (eq_refl A a) (eq_refl A a) (eq_refl A a) beta)")
f_equal_2
exact "whisker_l_refl A a beta"
trans ("eq_trans (a = a :> A) (eq_refl A a) (eq_refl A a) (eq_refl A a) "
++ "(whisker_r A a a a (eq_refl A a) (eq_refl A a) (eq_refl A a) alpha) "
++ "(whisker_l A a a a (eq_refl A a) (eq_refl A a) (eq_refl A a) beta)")
f_equal_1
f_equal_2
exact "whisker_r_refl A a alpha"
trans ("eq_trans (a = a :> A) (eq_refl A a) (eq_refl A a) (eq_refl A a) "
++ "(whisker_l A a a a (eq_refl A a) (eq_refl A a) (eq_refl A a) beta) "
++ "(whisker_r A a a a (eq_refl A a) (eq_refl A a) (eq_refl A a) alpha)")
exact "whisker_rl_lr A a a a (eq_refl A a) (eq_refl A a) alpha (eq_refl A a) (eq_refl A a) beta"
trans ("eq_trans (a = a :> A) (eq_refl A a) (eq_refl A a) (eq_refl A a) "
++ "(whisker_l A a a a (eq_refl A a) (eq_refl A a) (eq_refl A a) beta) "
++ "alpha")
f_equal_2
sym
exact "whisker_r_refl A a alpha"
f_equal_1
f_equal_2
sym
exact "whisker_l_refl A a beta"
qed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment