1{-# LANGUAGE MultiParamTypeClasses, FlexibleInstances #-}
3{- Implements a proof state, some primitive tactics for manipulating
4 proofs, and some high level commands for introducing new theorems,
5 evaluation/checking inside the proof system, etc. --}
7module ProofState(ProofState(..), newProof, envAtFocus, goalAtFocus,
8 Tactic(..), processTactic) where
15import Control.Monad.State
16import Control.Applicative
20data ProofState = PS { thname :: Name,
21 holes :: [Name], -- holes still to be solved
22 nextname :: Int, -- name supply
23 pterm :: Term, -- current proof term
24 ptype :: Type, -- original goal
29data Goal = GD { premises :: Env,
30 goalType :: Binder Term
50data TacticAction = AddGoal Name -- add a new goal, solve immediately
51 | NextGoal Name -- add a new goal, solve it after current one
52 | FocusGoal Name -- focus on this goal next
53 | MoveGoal Name -- move this goal to the end of the hole queue
55 | AlsoSolved Name Term -- goals solved by unification
58-- Some utilites on proof and tactic states
60instance Show ProofState where
61 show (PS nm [] _ tm _ _ _) = show nm ++ ": no more goals"
62 show (PS nm (h:hs) _ tm _ ctxt _)
63 = let OK g = goal (Just h) tm
65 showPs wkenv (reverse wkenv) ++ "\n" ++
66 "-------------------------------- (" ++ show nm ++
68 show h ++ " : " ++ showG wkenv (goalType g) ++ "\n"
69 where showPs env [] = ""
70 showPs env ((n, Let t v):bs)
71 = " " ++ show n ++ " : " ++
72 showEnv env (normalise ctxt env t) ++ " = " ++
73 showEnv env (normalise ctxt env v) ++
75 showPs env ((n, b):bs)
76 = " " ++ show n ++ " : " ++
77 showEnv env (normalise ctxt env (binderTy b)) ++
79 showG ps (Guess t v) = showEnv ps (normalise ctxt ps t) ++
80 " =?= " ++ showEnv ps v
81 showG ps b = showEnv ps (binderTy b)
84same (Just x) n = x == n
87hole (Guess _ _) = True
90holeName i = MN i "hole"
92getName :: Monad m => String -> StateT TState m Name
93getName tag = do (n, ts) <- get
97action :: Monad m => TacticAction -> StateT TState m ()
98action a = do (n, ts) <- get
101newProof :: Name -> Context -> Type -> ProofState
102newProof n ctxt ty = let h = holeName 0
104 PS n [h] 1 (Bind h (Hole ty') (P Bound h ty')) ty ctxt False
106type TState = (Int, [TacticAction])
107type RunTactic = Context -> Env -> Term -> StateT TState TC Term
108type Hole = Maybe Name -- Nothing = default hole, first in list in proof state
110envAtFocus :: ProofState -> TC Env
112 | not $ null (holes ps) = do g <- goal (Just (head (holes ps))) (pterm ps)
114 | otherwise = fail "No holes"
116goalAtFocus :: ProofState -> TC Type
118 | not $ null (holes ps) = do g <- goal (Just (head (holes ps))) (pterm ps)
119 return (binderTy (goalType g))
121goal :: Hole -> Term -> TC Goal
122goal h tm = g [] tm where
123 g env (Bind n b sc) | hole b && same h n = return $ GD env b
125 = gb env b `mplus` g ((n, b):env) sc
126 g env (App f a) = g env f `mplus` g env a
127 g env t = Error "Can't find hole"
129 gb env (Let t v) = g env t `mplus` g env v
130 gb env (Guess t v) = g env t `mplus` g env v
131 gb env t = g env (binderTy t)
133tactic :: Hole -> ProofState -> Context -> RunTactic -> StateT TState TC ProofState
134tactic h ps ctxt f = do let tm = pterm ps
136 return (ps { pterm = tm' })
138 atH env binder@(Bind n b sc)
139 | hole b && same h n = f ctxt env binder
141 = pure Bind <*> pure n <*> atHb env b <*> atH ((n,b) : env) sc
142 atH env (App f a) = pure App <*> atH env f <*> atH env a
145 atHb env (Let t v) = pure Let <*> atH env t <*> atH env v
146 atHb env (Guess t v) = pure Guess <*> atH env t <*> atH env v
147 atHb env t = do ty' <- atH env (binderTy t)
148 return $ t { binderTy = ty' }
151attack ctxt env (Bind x (Hole t) sc)
152 = do h <- getName "hole"
154 return $ Bind x (Guess t (newtm h)) sc
156 newtm h = Bind h (Hole t) (P Bound h t)
157attack ctxt env _ = fail "Not an attackable hole"
159claim :: Name -> Raw -> RunTactic
160claim n ty ctxt env t =
161 do (tyv, tyt) <- lift $ check ctxt env ty
162 lift $ isSet ctxt env tyt
164 return $ Bind n (Hole tyv) t -- (weakenTm 1 t)
166focus :: Name -> RunTactic
167focus n ctxt env t = do action (FocusGoal n)
170movelast :: Name -> RunTactic
171movelast n ctxt env t = do action (MoveGoal n)
178fill :: Raw -> RunTactic
179fill guess ctxt env (Bind x (Hole ty) sc) =
180 do (val, valty) <- lift $ check ctxt env guess
181 lift $ converts ctxt env valty ty
182 return $ Bind x (Guess ty val) sc
183fill _ _ _ _ = fail "Can't fill here."
185-- As fill, but attempts to solve other goals by unification
187unify_fill :: Raw -> RunTactic
188unify_fill guess ctxt env (Bind x (Hole ty) sc) =
189 do (val, valty) <- lift $ check ctxt env guess
190 ns <- lift $ unify ctxt env valty ty
192 return $ Bind x (Guess ty val) sc
194 solve_all [] = return ()
195 solve_all ((n, tm): ns) = do action (AlsoSolved n tm)
197unify_fill _ _ _ _ = fail "Can't fill here."
200solve ctxt env (Bind x (Guess ty val) sc)
201 | pureTerm val = do action (Solved x)
202 return $ Bind x (Let ty val) sc -- instantiate val (pToV x sc)
203 | otherwise = fail "I see a hole in your solution."
204solve _ _ _ = fail "Not a guess."
206intro :: Name -> RunTactic
207intro n ctxt env (Bind x (Hole t) (P _ x' _)) | x == x' =
208 do let t' = normalise ctxt env t
210 Bind y (Pi s) t -> let t' = instantiate (P Bound n s) (pToV y t) in
211 return $ Bind n (Lam s) (Bind x (Hole t') (P Bound x t'))
212 _ -> fail "Nothing to introduce"
213intro ctxt env _ _ = fail "Can't introduce here."
215forall :: Name -> Raw -> RunTactic
216forall n ty ctxt env (Bind x (Hole t) (P _ x' _)) | x == x' =
217 do (tyv, tyt) <- lift $ check ctxt env ty
218 lift $ isSet ctxt env tyt
219 lift $ isSet ctxt env t
220 return $ Bind n (Pi tyv) (Bind x (Hole t) (P Bound x t))
222patvar :: Name -> Raw -> RunTactic
223patvar n ty ctxt env (Bind x (Hole t) (P _ x' _)) | x == x' =
224 do (tyv, tyt) <- lift $ check ctxt env ty
225 lift $ isSet ctxt env tyt
226 return $ Bind n (PVar tyv) (Bind x (Hole t) (P Bound x t))
229compute ctxt env (Bind x (Hole ty) sc) =
230 do return $ Bind x (Hole (normalise ctxt env ty)) sc
232check_in :: Raw -> RunTactic
233check_in t ctxt env tm =
234 do (val, valty) <- lift $ check ctxt env t
235 action (Log (showEnv env val ++ " : " ++ showEnv env valty))
238eval_in :: Raw -> RunTactic
239eval_in t ctxt env tm =
240 do (val, valty) <- lift $ check ctxt env t
241 let val' = normalise ctxt env val
242 let valty' = normalise ctxt env valty
243 action (Log (showEnv env val ++ " : " ++
245-- " in " ++ show env ++
247 showEnv env val' ++ " : " ++
252processTactic :: Tactic -> ProofState -> TC (ProofState, String)
253processTactic QED ps = case holes ps of
254 [] -> let tm = finalise (pterm ps) in
255 return (ps { done = True, pterm = tm },
256 "Proof complete: " ++ showEnv [] tm)
257 _ -> Error "Still holes to fill."
258processTactic ProofState ps = return (ps, showEnv [] (pterm ps))
261 [] -> Error "Nothing to fill in."
262 (h:_) -> do let n = nextname ps
263 (ps', (n', actions)) <- runStateT (process t h ps) (n, [])
264 return (ps' { nextname = n',
265 pterm = updateSolved (getSolved actions) (pterm ps'),
266 holes = goals (holes ps') actions },
269 logs (Log x : xs) = x ++ "\n" ++ logs xs
270 logs (_ : xs) = logs xs
273 goals g (AddGoal n : xs) = goals (n : g) xs
274 goals (g:gs) (NextGoal n : xs) = goals (g : n : gs) xs
275 goals g (FocusGoal n : xs)
276 | n `elem` g = goals (n : (g \\ [n])) xs
277 goals g (MoveGoal n : xs)
278 | n `elem` g = goals ((g \\ [n]) ++ [n]) xs
279 goals g (Solved n : xs) = goals (g \\ [n]) xs
280 goals g (AlsoSolved n tm : xs) = goals (g \\ [n]) xs
281 goals g (_ : xs) = goals g xs
284 getSolved (AlsoSolved n tm : xs) = (n, tm) : getSolved xs
285 getSolved (_ : xs) = getSolved xs
287 updateSolved xs (Bind n b@(Hole _) t)
288 | Just v <- lookup n xs = Bind n (Let (binderTy b) v) (updateSolved xs t)
289 updateSolved xs (Bind n b t)
290 | otherwise = Bind n (fmap (updateSolved xs) b) (updateSolved xs t)
291 updateSolved xs (App f a) = App (updateSolved xs f) (updateSolved xs a)
292 updateSolved xs t = t
294process :: Tactic -> Name -> ProofState -> StateT TState TC ProofState
295process t h ps = tactic (Just h) ps (context ps) (mktac t)
296 where mktac Attack = attack
297 mktac (Claim n r) = claim n r
298 mktac (Fill r) = fill r
299 mktac (UnifyFill r) = unify_fill r
300 mktac Regret = regret
302 mktac Compute = compute
303 mktac (Intro n) = intro n
304 mktac (Forall n t) = forall n t
305 mktac (PatVar n t) = patvar n t
306 mktac (CheckIn r) = check_in r
307 mktac (EvalIn r) = eval_in r
308 mktac (Focus n) = focus n
309 mktac (MoveLast n) = movelast n
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list