@@ -1,36 +1,45 @@
1+{-|
2+Module : Idris.TypeSearch
3+Description : A Hoogle for Idris.
4+Copyright :
5+License : BSD3
6+Maintainer : The Idris Community.
7+-}
18{-# LANGUAGE ScopedTypeVariables #-}
29
310module Idris.TypeSearch (
4− searchByType, searchPred, defaultScoreFunction
5−) where
11+ searchByType
12+ , searchPred
13+ , defaultScoreFunction
14+ ) where
615
716import Control.Applicative (Applicative (..), (<$>), (<*>), (<|>))
8−import Control.Arrow (first, second, (&&&), (***))
9−import Control.Monad (when, guard)
10−
11−import Data.List (find, partition, (\\))
12−import Data.Map (Map)
13−import qualified Data.Map as M
14−import Data.Maybe (catMaybes, fromMaybe, isJust, maybeToList, mapMaybe)
15−import Data.Monoid (Monoid (mempty, mappend))
16−import Data.Ord (comparing)
17+import Control.Arrow (first, second, (&&&), (***))
18+import Control.Monad (when, guard)
19+
20+import Data.List (find, partition, (\\))
21+import Data.Map (Map)
22+import qualified Data.Map as M
23+import Data.Maybe (catMaybes, fromMaybe, isJust, maybeToList, mapMaybe)
24+import Data.Monoid (Monoid (mempty, mappend))
25+import Data.Ord (comparing)
1726import qualified Data.PriorityQueue.FingerTree as Q
18−import Data.Set (Set)
19−import qualified Data.Set as S
20−import qualified Data.Text as T (pack, isPrefixOf)
21−import Data.Traversable (traverse)
22−
23−import Idris.AbsSyntax (addUsingConstraints, addImpl, getIState, putIState, implicit, logLvl)
24−import Idris.AbsSyntaxTree (class_instances, ClassInfo, defaultSyntax, eqTy, Idris,
25− IState (idris_classes, idris_docstrings, tt_ctxt, idris_outputmode),
26− implicitAllowed, OutputMode(..), PTerm, toplevel)
27+import Data.Set (Set)
28+import qualified Data.Set as S
29+import qualified Data.Text as T (pack, isPrefixOf)
30+import Data.Traversable (traverse)
31+
32+import Idris.AbsSyntax (addUsingConstraints, addImpl, getIState, putIState, implicit, logLvl)
33+import Idris.AbsSyntaxTree (class_instances, ClassInfo, defaultSyntax, eqTy, Idris
34+ , IState (idris_classes, idris_docstrings, tt_ctxt, idris_outputmode),
35+ implicitAllowed, OutputMode(..), PTerm, toplevel)
2736import Idris.Core.Evaluate (Context (definitions), Def (Function, TyDecl, CaseOp), normaliseC)
28−import Idris.Core.TT hiding (score)
29−import Idris.Core.Unify (match_unify)
30−import Idris.Delaborate (delabTy)
31−import Idris.Docstrings (noDocs, overview)
32−import Idris.Elab.Type (elabType)
33−import Idris.Output (iputStrLn, iRenderOutput, iPrintResult, iRenderError, iRenderResult, prettyDocumentedIst)
37+import Idris.Core.TT hiding (score)
38+import Idris.Core.Unify (match_unify)
39+import Idris.Delaborate (delabTy)
40+import Idris.Docstrings (noDocs, overview)
41+import Idris.Elab.Type (elabType)
42+import Idris.Output (iputStrLn, iRenderOutput, iPrintResult, iRenderError, iRenderResult, prettyDocumentedIst)
3443import Idris.IBC
3544
3645import Prelude hiding (pred)
@@ -40,9 +49,9 @@ import Util.Pretty (text, char, vsep, (<>), Doc, annotate)
4049searchByType :: [String] -> PTerm -> Idris ()
4150searchByType pkgs pterm = do
4251 i <- getIState -- save original
43− when (not (null pkgs)) $
52+ when (not (null pkgs)) $
4453 iputStrLn $ "Searching packages: " ++ showSep ", " pkgs
45−
54+
4655 mapM_ loadPkgIndex pkgs
4756 pterm' <- addUsingConstraints syn emptyFC pterm
4857 pterm'' <- implicit toplevel syn name pterm'
@@ -67,9 +76,9 @@ searchByType pkgs pterm = do
6776 name = sMN 0 "searchType" -- name
6877
6978-- | Conduct a type-directed search using a given match predicate
70−searchUsing :: (IState -> Type -> [(Name, Type)] -> [(Name, a)])
79+searchUsing :: (IState -> Type -> [(Name, Type)] -> [(Name, a)])
7180 -> IState -> Type -> [(Name, a)]
72−searchUsing pred istate ty = pred istate nty . concat . M.elems $
81+searchUsing pred istate ty = pred istate nty . concat . M.elems $
7382 M.mapWithKey (\key -> M.toAscList . M.mapMaybe (f key)) (definitions ctxt)
7483 where
7584 nty = normaliseC ctxt [] ty
@@ -81,7 +90,7 @@ searchUsing pred istate ty = pred istate nty . concat . M.elems $
8190 special :: Name -> Bool
8291 special (NS n _) = special n
8392 special (SN _) = True
84− special (UN n) = T.pack "default#" `T.isPrefixOf` n
93+ special (UN n) = T.pack "default#" `T.isPrefixOf` n
8594 || n `elem` map T.pack ["believe_me", "really_believe_me"]
8695 special _ = False
8796
@@ -117,10 +126,10 @@ reverseDag xs = map f xs where
117126
118127-- run vToP first!
119128-- | Compute a directed acyclic graph corresponding to the
120−-- arguments of a function.
129+-- arguments of a function.
121130-- returns [(the name and type of the bound variable
122131-- the names in the type of the bound variable)]
123−computeDagP :: Ord n
132+computeDagP :: Ord n
124133 => (TT n -> Bool) -- ^ filter to remove some arguments
125134 -> TT n
126135 -> ([((n, TT n), Set n)], [(n, TT n)], TT n)
@@ -196,7 +205,7 @@ displayScore score = case both noMods (asymMods score) of
196205 Sided True False -> annotated LT "<" -- found type is more general than searched type
197206 Sided False True -> annotated GT ">" -- searched type is more general than found type
198207 Sided False False -> text "_"
199− where
208+ where
200209 annotated ordr = annotate (AnnSearchResult ordr) . text
201210 noMods (Mods app tcApp tcIntro) = app + tcApp + tcIntro == 0
202211
@@ -208,19 +217,19 @@ scoreCriterion (Score _ _ amods) = not
208217 ( sided (&&) (both ((> 0) . argApp) amods)
209218 || sided (+) (both argApp amods) > 4
210219 || sided (||) (both (\(Mods _ tcApp tcIntro) -> tcApp > 3 || tcIntro > 3) amods)
211− )
220+ )
212221
213222-- | Convert a 'Score' to an 'Int' to provide an order for search results.
214223-- Lower scores are better.
215224defaultScoreFunction :: Score -> Int
216−defaultScoreFunction (Score trans eqFlip amods) =
225+defaultScoreFunction (Score trans eqFlip amods) =
217226 trans + eqFlip + linearPenalty + upAndDowncastPenalty
218227 where
219228 -- prefer finding a more general type to a less general type
220− linearPenalty = (\(Sided l r) -> 3 * l + r)
229+ linearPenalty = (\(Sided l r) -> 3 * l + r)
221230 (both (\(Mods app tcApp tcIntro) -> 3 * app + 4 * tcApp + 2 * tcIntro) amods)
222231 -- it's very bad to have *both* upcasting and downcasting
223− upAndDowncastPenalty = 100 *
232+ upAndDowncastPenalty = 100 *
224233 sided (*) (both (\(Mods app tcApp tcIntro) -> 2 * app + tcApp + tcIntro) amods)
225234
226235instance Ord Score where
@@ -237,7 +246,7 @@ instance Monoid AsymMods where
237246
238247instance Monoid Score where
239248 mempty = Score 0 0 mempty
240− (Score t e mods) `mappend` (Score t' e' mods') = Score (t + t') (e + e') (mods `mappend` mods')
249+ (Score t e mods) `mappend` (Score t' e' mods') = Score (t + t') (e + e') (mods `mappend` mods')
241250
242251-- | A directed acyclic graph representing the arguments to a function
243252-- The 'Int' represents the position of the argument (1st argument, 2nd, etc.)
@@ -311,7 +320,7 @@ flipEqualities t = case t of
311320 [(0, eq1), (1, app (app (app (app eq tyR) tyL) valR) valL)]
312321 Bind n binder sc -> (\bind' (j, sc') -> (fst (binderTy bind') + j, Bind n (fmap snd bind') sc'))
313322 <$> traverse flipEqualities binder <*> flipEqualities sc
314− App _ f x -> (\(i, f') (j, x') -> (i + j, app f' x'))
323+ App _ f x -> (\(i, f') (j, x') -> (i + j, app f' x'))
315324 <$> flipEqualities f <*> flipEqualities x
316325 t' -> [(0, t')]
317326 where app = App Complete
@@ -329,13 +338,13 @@ matchTypesBulk istate maxScore type1 types = getAllResults startQueueOfQueues wh
329338 where
330339 ty2s = (\(i, dag) (j, retTy) -> (i + j, dag, retTy))
331340 <$> flipEqualitiesDag dag2 <*> flipEqualities retTy2
332− flipEqualitiesDag dag = case dag of
341+ flipEqualitiesDag dag = case dag of
333342 [] -> [(0, [])]
334− ((n, ty), (pos, deps)) : xs ->
343+ ((n, ty), (pos, deps)) : xs ->
335344 (\(i, ty') (j, xs') -> (i + j , ((n, ty'), (pos, deps)) : xs'))
336345 <$> flipEqualities ty <*> flipEqualitiesDag xs
337346 startStates (numEqFlips, sndDag, sndRetTy) = do
338− state <- unifyQueue (State startingHoles
347+ state <- unifyQueue (State startingHoles
339348 (Sided (dag1, typeClassArgs1) (sndDag, typeClassArgs2))
340349 (mempty { equalityFlips = numEqFlips }) usedns) [(retTy1, sndRetTy)]
341350 return (score state, state)
@@ -346,7 +355,7 @@ matchTypesBulk istate maxScore type1 types = getAllResults startQueueOfQueues wh
346355 usedns = map fst startingHoles
347356 startingHoles = argNames1 ++ argNames2
348357
349− startingTypes = [(retTy1, retTy2)]
358+ startingTypes = [(retTy1, retTy2)]
350359
351360
352361 startQueueOfQueues :: Q.PQueue Score (info, Q.PQueue Score State)
@@ -372,14 +381,14 @@ matchTypesBulk istate maxScore type1 types = getAllResults startQueueOfQueues wh
372381 (dag1, typeClassArgs1, retTy1) = makeDag type1
373382 argNames1 = map fst dag1
374383 makeDag :: Type -> (ArgsDAG, Classes, Type)
375− makeDag = first3 (zipWith (\i (ty, deps) -> (ty, (i, deps))) [0..] . reverseDag) .
384+ makeDag = first3 (zipWith (\i (ty, deps) -> (ty, (i, deps))) [0..] . reverseDag) .
376385 computeDagP (isTypeClassArg classInfo) . vToP . unLazy
377386 first3 f (a,b,c) = (f a, b, c)
378−
387+
379388 -- update our state with the unification resolutions
380389 resolveUnis :: [(Name, Type)] -> State -> Maybe (State, [(Type, Type)])
381390 resolveUnis [] state = Just (state, [])
382− resolveUnis ((name, term@(P Bound name2 _)) : xs)
391+ resolveUnis ((name, term@(P Bound name2 _)) : xs)
383392 state | isJust findArgs = do
384393 ((ty1, ix1), (ty2, ix2)) <- findArgs
385394
@@ -408,7 +417,7 @@ matchTypesBulk istate maxScore type1 types = getAllResults startQueueOfQueues wh
408417 -- due to injectivity
409418 matchedVarMap = usedVars term
410419 bothT f (x, y) = (f x, f y)
411− (injUsedVars, notInjUsedVars) = bothT M.keys . M.partition id . M.filterWithKey (\k _-> k `elem` map fst hs) $ M.map snd matchedVarMap
420+ (injUsedVars, notInjUsedVars) = bothT M.keys . M.partition id . M.filterWithKey (\k _-> k `elem` map fst hs) $ M.map snd matchedVarMap
412421 varsInTy = injUsedVars ++ notInjUsedVars
413422 toDelete = name : varsInTy
414423 deleteMany = foldr (.) id (map deleteName toDelete)
@@ -417,7 +426,7 @@ matchTypesBulk istate maxScore type1 types = getAllResults startQueueOfQueues wh
417426
418427 addScore additions theState = theState { score = let s = score theState in
419428 s { asymMods = asymMods s `mappend` additions } }
420− state' = state { holes = filter (not . (`elem` toDelete) . fst) hs
429+ state' = state { holes = filter (not . (`elem` toDelete) . fst) hs
421430 , argsAndClasses = both (modifyTypes (subst name term) . deleteMany) (argsAndClasses state) }
422431 nextStep = resolveUnis xs state'
423432
@@ -427,8 +436,8 @@ matchTypesBulk istate maxScore type1 types = getAllResults startQueueOfQueues wh
427436 unifyQueue state [] = return state
428437 unifyQueue state ((ty1, ty2) : queue) = do
429438 --trace ("go: \n" ++ show state) True `seq` return ()
430− res <- tcToMaybe $ match_unify ctxt [ (n, Pi Nothing ty (TType (UVar 0))) | (n, ty) <- holes state]
431− (ty1, Nothing)
439+ res <- tcToMaybe $ match_unify ctxt [ (n, Pi Nothing ty (TType (UVar 0))) | (n, ty) <- holes state]
440+ (ty1, Nothing)
432441 (ty2, Nothing) [] (map fst $ holes state) []
433442 (state', queueAdditions) <- resolveUnis res state
434443 guard $ scoreCriterion (score state')
@@ -453,7 +462,7 @@ matchTypesBulk istate maxScore type1 types = getAllResults startQueueOfQueues wh
453462 nextStepsQueue :: Q.PQueue Score State -> Maybe (Either (Q.PQueue Score State) Score)
454463 nextStepsQueue queue = do
455464 ((nextScore, next), rest) <- Q.minViewWithKey queue
456− Just $ if isFinal next
465+ Just $ if isFinal next
457466 then Right nextScore
458467 else let additions = if scoreCriterion nextScore
459468 then Q.fromList [ (score state, state) | state <- nextSteps next ]
@@ -469,19 +478,19 @@ matchTypesBulk istate maxScore type1 types = getAllResults startQueueOfQueues wh
469478 nextSteps :: State -> [State]
470479
471480 -- Stage 3 - match typeclasses
472− nextSteps (State [] unresolved@(Sided ([], c1) ([], c2)) scoreAcc usedns) =
481+ nextSteps (State [] unresolved@(Sided ([], c1) ([], c2)) scoreAcc usedns) =
473482 if null results3 then results4 else results3
474483 where
475484 -- try to match a typeclass argument from the left with a typeclass argument from the right
476485 results3 =
477− catMaybes [ unifyQueue (State []
486+ catMaybes [ unifyQueue (State []
478487 (Sided ([], deleteFromArgList n1 c1)
479488 ([], map (second subst2for1) (deleteFromArgList n2 c2)))
480− scoreAcc usedns) [(ty1, ty2)]
489+ scoreAcc usedns) [(ty1, ty2)]
481490 | (n1, ty1) <- c1, (n2, ty2) <- c2, let subst2for1 = psubst n2 (P Bound n1 ty1)]
482491
483492 -- try to hunt match a typeclass constraint by replacing it with an instance
484− results4 = [ State [] (both (\(cs, _, _) -> ([], cs)) sds)
493+ results4 = [ State [] (both (\(cs, _, _) -> ([], cs)) sds)
485494 (scoreAcc `mappend` Score 0 0 (both (\(_, amods, _) -> amods) sds))
486495 (usedns ++ sided (++) (both (\(_, _, hs) -> hs) sds))
487496 | sds <- allMods ]
@@ -512,10 +521,10 @@ matchTypesBulk istate maxScore type1 types = getAllResults startQueueOfQueues wh
512521 canBeFirst = map fst . filter (S.null . snd . snd)
513522
514523 -- try to match an argument from the left with an argument from the right
515− results1 = catMaybes [ unifyQueue (State (filter (not . (`elem` [n1,n2]) . fst) hs)
516− (Sided (deleteFromDag n1 dagL, c1)
524+ results1 = catMaybes [ unifyQueue (State (filter (not . (`elem` [n1,n2]) . fst) hs)
525+ (Sided (deleteFromDag n1 dagL, c1)
517526 (inArgTys subst2for1 $ deleteFromDag n2 dagR, map (second subst2for1) c2))
518− scoreAcc usedns) [(ty1, ty2)]
527+ scoreAcc usedns) [(ty1, ty2)]
519528 | (n1, ty1) <- canBeFirst dagL, (n2, ty2) <- canBeFirst dagR
520529 , let subst2for1 = psubst n2 (P Bound n1 ty1)]
521530
@@ -523,7 +532,7 @@ matchTypesBulk istate maxScore type1 types = getAllResults startQueueOfQueues wh
523532
524533 -- Stage 2 - simply introduce a subset of the typeclasses
525534 -- we've finished, so take some classes
526− takeSomeClasses (State [] unresolved@(Sided ([], _) ([], _)) scoreAcc usedns) =
535+ takeSomeClasses (State [] unresolved@(Sided ([], _) ([], _)) scoreAcc usedns) =
527536 map statesFromMods . prod $ both (classMods . snd) unresolved
528537 where
529538 swap (Sided l r) = Sided r l
@@ -532,7 +541,7 @@ matchTypesBulk istate maxScore type1 types = getAllResults startQueueOfQueues wh
532541 mods = swap (both snd sides) in
533542 State [] classes (scoreAcc `mappend` (mempty { asymMods = mods })) usedns
534543 classMods :: Classes -> [(Classes, AsymMods)]
535− classMods cs = let lcs = length cs in
544+ classMods cs = let lcs = length cs in
536545 [ (cs', mempty { typeClassIntro = lcs - length cs' }) | cs' <- subsets cs ]
537546 prod :: Sided [a] -> [Sided a]
538547 prod (Sided ls rs) = [Sided l r | l <- ls, r <- rs]