on master help sign in
More precision for trivial

Need more control in type class resolution to say where it's okay to resolve by things containing metavariables (i.e. it's okay to solve non-determining arguments in type class resolution, so it's okay for those arguments to be holes) Fixes #2136

commit0d01d0d8489b11f9baca689458b529c324e874dc authorEdwin Brady <ecb10@st-andrews.ac.uk> dateSun 17 May 2015, 19:56 (11 years ago) parentf2c78d9
2 files changed+63−17
src/Idris/Elab/Term.hs+39−14 src/Idris/ProofSearch.hs+24−3
src/Idris/Elab/Term.hs+39−14
@@ -1451,6 +1451,8 @@ solveAutos ist fn ambigok
14511451
14521452trivial' ist
14531453 = trivial (elab ist toplevel ERHS [] (sMN 0 "tac")) ist
1454+trivialHoles' h ist
1455+ = trivialHoles h (elab ist toplevel ERHS [] (sMN 0 "tac")) ist
14541456proofSearch' ist rec ambigok depth prv top n hints
14551457 = do unifyProblems
14561458 proofSearch rec prv ambigok (not prv) depth
@@ -1473,7 +1475,13 @@ resTC' tcs def topholes 1 topg fn ist = try' (trivial' ist) (resolveTC def False
14731475resTC' tcs defaultOn topholes depth topg fn ist
14741476 = do compute
14751477 g <- goal
1476− let argsok = tcArgsOK g topholes
1478+ -- Resolution can proceed only if there is something concrete in the
1479+ -- determining argument positions. Keep track of the holes in the
1480+ -- non-determining position, because it's okay for 'trivial' to solve
1481+ -- those holes and no others.
1482+ let (argsok, okholePos) = case tcArgsOK g topholes of
1483+ Nothing -> (False, [])
1484+ Just hs -> (True, hs)
14771485 if not argsok -- && not mvok)
14781486 then lift $ tfail $ CantResolve True topg
14791487 else do
@@ -1481,30 +1489,47 @@ resTC' tcs defaultOn topholes depth topg fn ist
14811489 ulog <- getUnifyLog
14821490 hs <- get_holes
14831491 env <- get_env
1484− traceWhen ulog ("Resolving class " ++ show g ++ "\nin" ++ show env) $
1485− try' (trivial' ist)
1486− (do t <- goal
1487− let (tc, ttypes) = unApply (getRetTy t)
1488− addDefault t tc ttypes
1492+ t <- goal
1493+ let (tc, ttypes) = unApply (getRetTy t)
1494+ let okholes = case tc of
1495+ P _ n _ -> zip (repeat n) okholePos
1496+ _ -> []
1497+
1498+ traceWhen ulog ("Resolving class " ++ show g ++ "\nin" ++ show env ++ "\n" ++ show okholes) $
1499+ try' (trivialHoles' okholes ist)
1500+ (do addDefault t tc ttypes
14891501 let stk = elab_stack ist
14901502 let insts = findInstances ist t
14911503 tm <- get_term
14921504 blunderbuss t depth stk (stk ++ insts)) True
14931505 where
1506+ -- returns Just hs if okay, where hs are holes which are okay in the
1507+ -- goal, or Nothing if not okay to proceed
14941508 tcArgsOK ty hs | (P _ nc _, as) <- unApply (getRetTy ty), nc == numclass && defaultOn
1495− = True
1496− tcArgsOK ty hs -- if any arguments are metavariables, postpone
1509+ = Just []
1510+ tcArgsOK ty hs -- if any determining arguments are metavariables, postpone
14971511 = let (f, as) = unApply (getRetTy ty) in
14981512 case f of
14991513 P _ cn _ -> case lookupCtxtExact cn (idris_classes ist) of
15001514 Just ci -> tcDetArgsOK 0 (class_determiners ci) hs as
1501− Nothing -> not $ any (isMeta hs) as
1502− _ -> not $ any (isMeta hs) as
1503−
1515+ Nothing -> if any (isMeta hs) as
1516+ then Nothing
1517+ else Just []
1518+ _ -> if any (isMeta hs) as
1519+ then Nothing
1520+ else Just []
1521+
1522+ -- return the list of argument positions which can safely be a hole
1523+ -- or Nothing if one of the determining arguments is a hole
15041524 tcDetArgsOK i ds hs (x : xs)
1505− | i `elem` ds = not (isMeta hs x) && tcDetArgsOK (i + 1) ds hs xs
1506− | otherwise = tcDetArgsOK (i + 1) ds hs xs
1507− tcDetArgsOK _ _ _ [] = True
1525+ | i `elem` ds = if isMeta hs x
1526+ then Nothing
1527+ else tcDetArgsOK (i + 1) ds hs xs
1528+ | otherwise = do rs <- tcDetArgsOK (i + 1) ds hs xs
1529+ case x of
1530+ P _ n _ -> Just (i : rs)
1531+ _ -> Just rs
1532+ tcDetArgsOK _ _ _ [] = Just []
15081533
15091534 isMeta :: [Name] -> Term -> Bool
15101535 isMeta ns (P _ n _) = n `elem` ns
src/Idris/ProofSearch.hs+24−3
@@ -1,6 +1,6 @@
11{-# LANGUAGE PatternGuards #-}
22
3−module Idris.ProofSearch(trivial, proofSearch) where
3+module Idris.ProofSearch(trivial, trivialHoles, proofSearch) where
44
55import Idris.Core.Elaborate hiding (Tactic(..))
66import Idris.Core.TT
@@ -22,7 +22,11 @@ import Debug.Trace
2222-- Pass in a term elaborator to avoid a cyclic dependency with ElabTerm
2323
2424trivial :: (PTerm -> ElabD ()) -> IState -> ElabD ()
25−trivial elab ist = try' (do elab (PApp (fileFC "prf") (PRef (fileFC "prf") eqCon) [pimp (sUN "A") Placeholder False, pimp (sUN "x") Placeholder False])
25+trivial = trivialHoles []
26+
27+trivialHoles :: [(Name, Int)] -> (PTerm -> ElabD ()) -> IState -> ElabD ()
28+trivialHoles ok elab ist
29+ = try' (do elab (PApp (fileFC "prf") (PRef (fileFC "prf") eqCon) [pimp (sUN "A") Placeholder False, pimp (sUN "x") Placeholder False])
2630 return ())
2731 (do env <- get_env
2832 g <- goal
@@ -33,11 +37,28 @@ trivial elab ist = try' (do elab (PApp (fileFC "prf") (PRef (fileFC "prf") eqCon
3337 tryAll ((x, b):xs)
3438 = do -- if type of x has any holes in it, move on
3539 hs <- get_holes
40+ let badhs = hs -- filter (flip notElem holesOK) hs
3641 g <- goal
37− if all (\n -> not (n `elem` hs)) (freeNames (binderTy b))
42+ -- anywhere but the top is okay for a hole, if holesOK set
43+ if -- all (\n -> not (n `elem` badhs)) (freeNames (binderTy b))
44+ holesOK hs (binderTy b)
3845 then try' (elab (PRef (fileFC "prf") x))
3946 (tryAll xs) True
4047 else tryAll xs
48+
49+ holesOK hs ap@(App _ _ _)
50+ | (P _ n _, args) <- unApply ap
51+ = holeArgsOK hs n 0 args
52+ holesOK hs (App _ f a) = holesOK hs f && holesOK hs a
53+ holesOK hs (P _ n _) = not (n `elem` hs)
54+ holesOK hs (Bind n b sc) = holesOK hs (binderTy b) &&
55+ holesOK hs sc
56+ holesOK hs _ = True
57+
58+ holeArgsOK hs n p [] = True
59+ holeArgsOK hs n p (a : as)
60+ | (n, p) `elem` ok = holeArgsOK hs n (p + 1) as
61+ | otherwise = holesOK hs a && holeArgsOK hs n (p + 1) as
4162
4263cantSolveGoal :: ElabD a
4364cantSolveGoal = do g <- goal