on master help sign in
Merge branch 'RyanGlScott-master'
commit0a6feb13f8e66e3e01eb6565518bb141c07bf31e authorDavid Raymond Christiansen <david@davidchristiansen.dk> dateFri 12 Sep 2014, 17:35 (12 years ago) parent60f3916bc0af86
27 files changed+436−201
.travis.yml+1 idris.cabal+3−3 libs/prelude/Decidable/Equality.idr+10−5 main/Main.hs+5 src/IRTS/Java/ASTBuilding.hs+1−1 src/Idris/AbsSyntax.hs+6−1 src/Idris/AbsSyntaxTree.hs+5−1 src/Idris/CaseSplit.hs+8−1 src/Idris/CmdOptions.hs+3−4 src/Idris/Core/Elaborate.hs+8 src/Idris/Core/Execute.hs+11−5 src/Idris/Core/ProofState.hs+1 src/Idris/Core/ProofTerm.hs+2 src/Idris/Core/TT.hs+2 src/Idris/Core/Typecheck.hs+4−13 src/Idris/Core/Unify.hs+6 src/Idris/Coverage.hs+29−20 src/Idris/Elab/Class.hs+6 src/Idris/Elab/Clause.hs+2−2 src/Idris/Elab/Utils.hs+3−3 src/Idris/Error.hs+76 src/Idris/Help.hs+2−1 src/Idris/PartialEval.hs+2 src/Idris/Providers.hs+5−2 src/Idris/REPL.hs+24 src/Idris/REPLParser.hs+1 src/Idris/TypeSearch.hs+210−139
.travis.yml+1
@@ -10,6 +10,7 @@ before_install:
1010 - sudo apt-get install hscolour
1111 # test dependency
1212 - sudo apt-get install -qq expect
13+ - cabal install alex-3.1.3
1314install:
1415 - cabal install -f FFI -f LLVM --only-dependencies --enable-tests
1516 - ghc-pkg list
idris.cabal+3−3
@@ -1,5 +1,5 @@
11Name: idris
2−Version: 0.9.14.1
2+Version: 0.9.14.2
33License: BSD3
44License-file: LICENSE
55Author: Edwin Brady
@@ -680,7 +680,7 @@ Library
680680 , filepath
681681 , fingertree >= 0.1
682682 , haskeline >= 0.7
683− , language-java >= 0.2.6
683+ , language-java >= 0.2.7
684684 , lens >= 4.1.1
685685 , mtl
686686 , parsers >= 0.9 && < 0.13
@@ -699,7 +699,7 @@ Library
699699 , xml
700700 , deepseq
701701 , zlib
702− , optparse-applicative >= 0.8
702+ , optparse-applicative >= 0.10
703703 Extensions: MultiParamTypeClasses
704704 , DeriveFoldable
705705 , DeriveTraversable
libs/prelude/Decidable/Equality.idr+10−5
@@ -201,7 +201,8 @@ instance DecEq a => DecEq (Vect n a) where
201201
202202instance DecEq Int where
203203 decEq x y = if x == y then Yes primitiveEq else No primitiveNotEq
204− where postulate primitiveEq : x = y
204+ where primitiveEq : x = y
205+ primitiveEq = believe_me (refl {x})
205206 postulate primitiveNotEq : x = y -> _|_
206207
207208--------------------------------------------------------------------------------
@@ -210,7 +211,8 @@ instance DecEq Int where
210211
211212instance DecEq Char where
212213 decEq x y = if x == y then Yes primitiveEq else No primitiveNotEq
213− where postulate primitiveEq : x = y
214+ where primitiveEq : x = y
215+ primitiveEq = believe_me (refl {x})
214216 postulate primitiveNotEq : x = y -> _|_
215217
216218--------------------------------------------------------------------------------
@@ -219,7 +221,8 @@ instance DecEq Char where
219221
220222instance DecEq Integer where
221223 decEq x y = if x == y then Yes primitiveEq else No primitiveNotEq
222− where postulate primitiveEq : x = y
224+ where primitiveEq : x = y
225+ primitiveEq = believe_me (refl {x})
223226 postulate primitiveNotEq : x = y -> _|_
224227
225228--------------------------------------------------------------------------------
@@ -228,7 +231,8 @@ instance DecEq Integer where
228231
229232instance DecEq Float where
230233 decEq x y = if x == y then Yes primitiveEq else No primitiveNotEq
231− where postulate primitiveEq : x = y
234+ where primitiveEq : x = y
235+ primitiveEq = believe_me (refl {x})
232236 postulate primitiveNotEq : x = y -> _|_
233237
234238--------------------------------------------------------------------------------
@@ -237,7 +241,8 @@ instance DecEq Float where
237241
238242instance DecEq String where
239243 decEq x y = if x == y then Yes primitiveEq else No primitiveNotEq
240− where postulate primitiveEq : x = y
244+ where primitiveEq : x = y
245+ primitiveEq = believe_me (refl {x})
241246 postulate primitiveNotEq : x = y -> _|_
242247
243248
main/Main.hs+5
@@ -37,6 +37,7 @@ import Paths_idris
3737-- Main program reads command line options, parses the main program, and gets
3838-- on with the REPL.
3939
40+main :: IO ()
4041main = do opts <- runArgParser
4142 runMain (runIdris opts)
4243
@@ -71,17 +72,21 @@ runIdris opts = do
7172 _ -> ifail "Too many packages"
7273 fs -> runIO $ mapM_ (buildPkg (WarnOnly `elem` opts)) fs
7374
75+showver :: IO b
7476showver = do putStrLn $ "Idris version " ++ ver
7577 exitWith ExitSuccess
7678
79+showLibs :: IO b
7780showLibs = do libFlags <- getLibFlags
7881 putStrLn libFlags
7982 exitWith ExitSuccess
8083
84+showLibdir :: IO b
8185showLibdir = do dir <- getIdrisLibDir
8286 putStrLn dir
8387 exitWith ExitSuccess
8488
89+showIncs :: IO b
8590showIncs = do incFlags <- getIncFlags
8691 putStrLn incFlags
8792 exitWith ExitSuccess
src/IRTS/Java/ASTBuilding.hs+1−1
@@ -60,7 +60,7 @@ localVar i = Ident $ "loc" ++ show i
6060
6161(@!) :: Exp -> Int -> ArrayIndex
6262(@!) target pos =
63− ArrayIndex target (Lit $ Int (toInteger pos))
63+ ArrayIndex target [Lit $ Int (toInteger pos)]
6464
6565(@:=) :: Either ArrayIndex Ident -> Exp -> BlockStmt
6666(@:=) (Right lhs) rhs =
src/Idris/AbsSyntax.hs+6−1
@@ -17,6 +17,7 @@ import Util.DynamicLinker
1717import System.Console.Haskeline
1818import System.IO
1919
20+import Control.Applicative
2021import Control.Monad.State
2122import Control.Monad.Error(throwError)
2223
@@ -1663,7 +1664,11 @@ findStatics ist tm = trace (show tm) $
16631664 pos ns ss t = return t
16641665
16651666-- for 6.12/7 compatibility
1666−data EitherErr a b = LeftErr a | RightOK b
1667+data EitherErr a b = LeftErr a | RightOK b deriving ( Functor )
1668+
1669+instance Applicative (EitherErr a) where
1670+ pure = return
1671+ (<*>) = ap
16671672
16681673instance Monad (EitherErr a) where
16691674 return = RightOK
src/Idris/AbsSyntaxTree.hs+5−1
@@ -30,6 +30,8 @@ import Data.Either
3030import qualified Data.Set as S
3131import Data.Word (Word)
3232import Data.Maybe (fromMaybe)
33+import Data.Traversable (Traversable)
34+import Data.Foldable (Foldable)
3335
3436import Debug.Trace
3537
@@ -361,6 +363,7 @@ data Command = Quit
361363 | CallsWho Name
362364 | MakeDoc String -- IdrisDoc
363365 | Warranty
366+ | PrintDef Name
364367
365368data Opt = Filename String
366369 | Quiet
@@ -792,7 +795,7 @@ data PTactic' t = Intro [Name] | Intros | Focus Name
792795 | Skip
793796 | TFail [ErrorReportPart]
794797 | Qed | Abandon
795− deriving (Show, Eq, Functor)
798+ deriving (Show, Eq, Functor, Foldable, Traversable)
796799{-!
797800deriving instance Binary PTactic'
798801deriving instance NFData PTactic'
@@ -1820,3 +1823,4 @@ getErasureInfo ist n =
18201823 case lookupCtxtExact n (idris_optimisation ist) of
18211824 Just (Optimise inacc detagg) -> map fst inacc
18221825 Nothing -> []
1826+
src/Idris/CaseSplit.hs+8−1
@@ -5,10 +5,10 @@ module Idris.CaseSplit(splitOnLine, replaceSplits,
55 mkWith,
66 nameMissing,
77 getUniq, nameRoot) where
8−
98-- splitting a variable in a pattern clause
109
1110import Idris.AbsSyntax
11+import Idris.AbsSyntaxTree (Idris, IState, PTerm)
1212import Idris.ElabDecls
1313import Idris.ElabTerm
1414import Idris.Delaborate
@@ -91,9 +91,11 @@ data MergeState = MS { namemap :: [(Name, Name)],
9191 explicit :: [Name],
9292 updates :: [(Name, PTerm)] }
9393
94+addUpdate :: Name -> Idris.AbsSyntaxTree.PTerm -> State MergeState ()
9495addUpdate n tm = do ms <- get
9596 put (ms { updates = ((n, stripNS tm) : updates ms) } )
9697
98+inventName :: Idris.AbsSyntaxTree.IState -> Maybe Name -> Name -> State MergeState Name
9799inventName ist ty n =
98100 do ms <- get
99101 let supp = case ty of
@@ -115,11 +117,14 @@ inventName ist ty n =
115117 put (ms { invented = (n, n') : invented ms })
116118 return n'
117119
120+mkSupply :: [Name] -> [Name]
118121mkSupply ns = mkSupply' ns (map nextName ns)
119122 where mkSupply' xs ns' = xs ++ mkSupply ns'
120123
124+varlist :: [Name]
121125varlist = map (sUN . (:[])) "xyzwstuv" -- EB's personal preference :)
122126
127+stripNS :: Idris.AbsSyntaxTree.PTerm -> Idris.AbsSyntaxTree.PTerm
123128stripNS tm = mapPT dens tm where
124129 dens (PRef fc n) = PRef fc (nsroot n)
125130 dens t = t
@@ -310,6 +315,8 @@ replaceSplits l ups = updateRHSs 1 (map (rep (expandBraces l)) ups)
310315 , not (isSuffixOf ")" tm) = "(" ++ tm ++ ")"
311316 | otherwise = tm
312317
318+
319+getUniq :: (Show t, Num t) => [Char] -> t -> Idris ([Char], t)
313320getUniq nm i
314321 = do ist <- getIState
315322 let n = nameRoot [] nm ++ "_" ++ show i
src/Idris/CmdOptions.hs+3−4
@@ -57,7 +57,7 @@ runArgParser = do opts <- execParser $ info parser
5757
5858
5959pureArgParser :: [String] -> [Opt]
60−pureArgParser args = case execParserMaybe (info parser idm) args of
60+pureArgParser args = case getParseResult $ execParserPure (prefs idm) (info parser idm) args of
6161 Just opts -> preProcOpts opts []
6262 Nothing -> []
6363
@@ -74,7 +74,7 @@ parseFlags = many $
7474 <|> flag' Ideslave (long "ideslave")
7575 <|> flag' IdeslaveSocket (long "ideslave-socket")
7676 <|> (Client <$> strOption (long "client"))
77− <|> (OLogging <$> option (long "log" <> metavar "LEVEL" <> help "Debugging log level"))
77+ <|> (OLogging <$> option auto (long "log" <> metavar "LEVEL" <> help "Debugging log level"))
7878 <|> flag' NoBasePkgs (long "nobasepkgs")
7979 <|> flag' NoPrelude (long "noprelude")
8080 <|> flag' NoBuiltins (long "nobuiltins")
@@ -120,7 +120,7 @@ parseFlags = many $
120120 <|> flag' (OptLevel 2) (long "O2")
121121 <|> flag' (OptLevel 1) (long "O1")
122122 <|> flag' (OptLevel 0) (long "O0")
123− <|> (OptLevel <$> option (short 'O' <> long "level"))
123+ <|> (OptLevel <$> option auto (short 'O' <> long "level"))
124124 <|> (TargetTriple <$> strOption (long "target" <> metavar "TRIPLE" <> help "Select target triple (for llvm codegen)"))
125125 <|> (TargetCPU <$> strOption (long "cpu" <> metavar "CPU" <> help "Select target CPU e.g. corei7 or cortex-m3 (for LLVM codegen)"))
126126 <|> flag' (ColourREPL True) (long "colour" <> long "color" <> help "Force coloured output")
@@ -144,4 +144,3 @@ preProcOpts (x:xs) ys = preProcOpts xs (x:ys)
144144parseCodegen :: String -> Codegen
145145parseCodegen "bytecode" = Bytecode
146146parseCodegen cg = Via (map toLower cg)
147−
src/Idris/Core/Elaborate.hs+8
@@ -755,6 +755,14 @@ tryAll xs = tryAll' [] 999999 (cantResolve, 0) xs
755755 if (s >= i) then (lift (tfail err), s)
756756 else (f, i)
757757
758+prunStateT
759+ :: Int
760+ -> Bool
761+ -> [a]
762+ -> Control.Monad.State.Strict.StateT
763+ (ElabState t) (TC' Err) t1
764+ -> ElabState t
765+ -> TC' Err ((t1, Int, Idris.Core.Unify.Fails), ElabState t)
758766prunStateT pmax zok ps x s
759767 = case runStateT x s of
760768 OK (v, s'@(ES (p, _) _ _)) ->
src/Idris/Core/Execute.hs+11−5
@@ -51,8 +51,9 @@ readMay s = case reads s of
5151
5252data Lazy = Delayed ExecEnv Context Term | Forced ExecVal deriving Show
5353
54−newtype ExecState = ExecState { exec_dynamic_libs :: [DynamicLib] -- ^ Dynamic libs from idris monad
55− }
54+data ExecState = ExecState { exec_dynamic_libs :: [DynamicLib] -- ^ Dynamic libs from idris monad
55+ , binderNames :: [Name] -- ^ Used to uniquify binders when converting to TT
56+ }
5657
5758data ExecVal = EP NameType Name ExecVal
5859 | EV Int
@@ -80,9 +81,10 @@ instance Show ExecVal where
8081toTT :: ExecVal -> Exec Term
8182toTT (EP nt n ty) = (P nt n) <$> (toTT ty)
8283toTT (EV i) = return $ V i
83−toTT (EBind n b body) = do body' <- body $ EP Bound n EErased
84+toTT (EBind n b body) = do n' <- newN n
85+ body' <- body $ EP Bound n' EErased
8486 b' <- fixBinder b
85− Bind n b' <$> toTT body'
87+ Bind n' b' <$> toTT body'
8688 where fixBinder (Lam t) = Lam <$> toTT t
8789 fixBinder (Pi t k) = Pi <$> toTT t <*> toTT k
8890 fixBinder (Let t1 t2) = Let <$> toTT t1 <*> toTT t2
@@ -92,6 +94,10 @@ toTT (EBind n b body) = do body' <- body $ EP Bound n EErased
9294 fixBinder (Guess t1 t2) = Guess <$> toTT t1 <*> toTT t2
9395 fixBinder (PVar t) = PVar <$> toTT t
9496 fixBinder (PVTy t) = PVTy <$> toTT t
97+ newN n = do (ExecState hs ns) <- lift get
98+ let n' = uniqueName n ns
99+ lift (put (ExecState hs (n':ns)))
100+ return n'
95101toTT (EApp e1 e2) = do e1' <- toTT e1
96102 e2' <- toTT e2
97103 return $ App e1' e2'
@@ -115,7 +121,7 @@ mkEApp f (a:args) = mkEApp (EApp f a) args
115121
116122initState :: Idris ExecState
117123initState = do ist <- getIState
118− return $ ExecState (idris_dynamic_libs ist)
124+ return $ ExecState (idris_dynamic_libs ist) []
119125
120126type Exec = ErrorT Err (StateT ExecState IO)
121127
src/Idris/Core/ProofState.hs+1
@@ -815,6 +815,7 @@ updateProblems ctxt ns ps inj holes usupp = up ns ps where
815815 (ns', (x',y',env',err', while, um) : ps')
816816
817817-- attempt to solve remaining problems with match_unify
818+-- matchProblems :: Bool -> Elab' aux ()
818819matchProblems all ns ctxt ps inj holes = up ns ps where
819820 up ns [] = (ns, [])
820821 up ns ((x, y, env, err, while, um) : ps)
src/Idris/Core/ProofTerm.hs+2
@@ -114,9 +114,11 @@ mkProofTerm tm = PT Top [] tm []
114114getProofTerm :: ProofTerm -> Term
115115getProofTerm (PT path _ sub ups) = rebuildTerm sub (updateSolvedPath ups path)
116116
117+same :: Eq a => Maybe a -> a -> Bool
117118same Nothing n = True
118119same (Just x) n = x == n
119120
121+hole :: Binder b -> Bool
120122hole (Hole _) = True
121123hole (Guess _ _) = True
122124hole _ = False
src/Idris/Core/TT.hs+2
@@ -1088,6 +1088,7 @@ unList tm = case unApply tm of
10881088forget :: TT Name -> Raw
10891089forget tm = forgetEnv [] tm
10901090
1091+forgetEnv :: [Name] -> TT Name -> Raw
10911092forgetEnv env (P _ n _) = Var n
10921093forgetEnv env (V i) = Var (env !! i)
10931094forgetEnv env (Bind n b sc) = let n' = uniqueName n env in
@@ -1154,6 +1155,7 @@ nextName (UN x) = let (num', nm') = T.span isDigit (T.reverse x)
11541155nextName (SN x) = SN (nextName' x)
11551156 where
11561157 nextName' (WhereN i f x) = WhereN i f (nextName x)
1158+ nextName' (WithN i n) = WithN i (nextName n)
11571159 nextName' (CaseN n) = CaseN (nextName n)
11581160 nextName' (MethodN n) = MethodN (nextName n)
11591161
src/Idris/Core/Typecheck.hs+4−13
@@ -51,17 +51,17 @@ isType ctxt env tm = isType' (normalise ctxt env tm)
5151 | otherwise = fail (showEnv env tm ++ " is not a Type")
5252
5353recheck :: Context -> Env -> Raw -> Term -> TC (Term, Type, UCs)
54−recheck = recheck_borrowing []
54+recheck = recheck_borrowing False []
5555
56−recheck_borrowing :: [Name] -> Context -> Env -> Raw -> Term ->
56+recheck_borrowing :: Bool -> [Name] -> Context -> Env -> Raw -> Term ->
5757 TC (Term, Type, UCs)
58−recheck_borrowing bs ctxt env tm orig
58+recheck_borrowing uniq_check bs ctxt env tm orig
5959 = let v = next_tvar ctxt in
6060 case runStateT (check' False ctxt env tm) (v, []) of -- holes banned
6161 Error (IncompleteTerm _) -> Error $ IncompleteTerm orig
6262 Error e -> Error e
6363 OK ((tm, ty), constraints) ->
64− do checkUnique bs ctxt env tm
64+ do when uniq_check $ checkUnique bs ctxt env tm
6565 return (tm, ty, constraints)
6666
6767check :: Context -> Env -> Raw -> TC (Term, Type)
@@ -281,20 +281,11 @@ checkUnique borrowed ctxt env tm
281281 chkBinders env (App f a) = do chkBinders env f; chkBinders env a
282282 chkBinders env (Bind n b t)
283283 = do chkBinderName env n b
284− -- Must be safe whether we evaluate the scope or binder first
285− -- (Surely there is a tidier rule than this...?)
286284 st <- get
287− chkBinders env (binderTy b)
288285 case b of
289286 Let t v -> chkBinders env v
290287 _ -> return ()
291288 chkBinders ((n, b) : env) t
292−-- put st
293−-- chkBinders env (binderTy b)
294−-- case b of
295−-- Let t v -> chkBinders env v
296−-- _ -> return ()
297−-- chkBinders ((n, b) : env) t
298289 chkBinders env t = return ()
299290
300291 chkBinderName :: Env -> Name -> Binder Term ->
src/Idris/Core/Unify.hs+6
@@ -84,6 +84,10 @@ match_unify ctxt env topx topy inj holes from =
8484 -- but it scares me. However, matching is never guaranteed to give a unique
8585 -- answer, merely a valid one, so perhaps we're okay.
8686 -- In other words: it may vanish without warning some day :)
87+ un :: [((Name, Name), TT Name)] -> TT Name -> TT Name ->
88+ StateT UInfo
89+ TC [(Name, TT Name)]
90+
8791 un names x tm@(App (P _ f (Bind fn (Pi t _) sc)) a)
8892 | (P (DCon _ _ _) _ _, _) <- unApply x,
8993 holeIn env f || f `elem` holes
@@ -237,6 +241,7 @@ expandLets env (x, tm) = (x, doSubst (reverse env) tm)
237241 doSubst (_ : env) tm
238242 = doSubst env tm
239243
244+hasv :: TT Name -> Bool
240245hasv (V x) = True
241246hasv (App f a) = hasv f || hasv a
242247hasv (Bind x b sc) = hasv (binderTy b) || hasv sc
@@ -660,6 +665,7 @@ recoverable (Bind _ (Lam _) sc) f = recoverable sc f
660665recoverable f (Bind _ (Lam _) sc) = recoverable f sc
661666recoverable x y = True
662667
668+errEnv :: [(a, Binder b)] -> [(a, b)]
663669errEnv = map (\(x, b) -> (x, binderTy b))
664670
665671holeIn :: Env -> Name -> Bool
src/Idris/Coverage.hs+29−20
@@ -120,26 +120,6 @@ genClauses fc n xs given
120120 as' <- mkArg as
121121 return (a':as')
122122
123−fnub xs = fnub' [] xs
124−
125−fnub' acc (x : xs) | x `qelem` acc = fnub' acc (filter (not.(quickEq x)) xs)
126− | otherwise = fnub' (x : acc) xs
127−fnub' acc [] = acc
128−
129−-- quick check for constructor equality
130−quickEq :: PTerm -> PTerm -> Bool
131−quickEq (PConstant n) (PConstant n') = n == n'
132−quickEq (PRef _ n) (PRef _ n') = n == n'
133−quickEq (PApp _ t as) (PApp _ t' as')
134− | length as == length as'
135− = quickEq t t' && and (zipWith quickEq (map getTm as) (map getTm as'))
136−quickEq Placeholder Placeholder = True
137−quickEq x y = False
138−
139−qelem x [] = False
140−qelem x (y : ys) | x `quickEq` y = True
141− | otherwise = qelem x ys
142−
143123-- FIXME: Just look for which one is the deepest, then generate all
144124-- possibilities up to that depth.
145125
@@ -244,6 +224,31 @@ genAll i args
244224 -> PApp fc (PRef fc x) (map (upd Placeholder) pargs)
245225 _ -> error "Can't happen - genAll"
246226
227+ fnub :: [PTerm] -> [PTerm]
228+ fnub xs = fnub' [] xs
229+
230+ fnub' :: [PTerm] -> [PTerm] -> [PTerm]
231+ fnub' acc (x : xs) | x `qelem` acc = fnub' acc (filter (not.(quickEq x)) xs)
232+ | otherwise = fnub' (x : acc) xs
233+ fnub' acc [] = acc
234+
235+ -- quick check for constructor equality
236+ quickEq :: PTerm -> PTerm -> Bool
237+ quickEq (PConstant n) (PConstant n') = n == n'
238+ quickEq (PRef _ n) (PRef _ n') = n == n'
239+ quickEq (PApp _ t as) (PApp _ t' as')
240+ | length as == length as'
241+ = quickEq t t' && and (zipWith quickEq (map getTm as) (map getTm as'))
242+ quickEq Placeholder Placeholder = True
243+ quickEq x y = False
244+
245+ qelem :: PTerm -> [PTerm] -> Bool
246+ qelem x [] = False
247+ qelem x (y : ys) | x `quickEq` y = True
248+ | otherwise = qelem x ys
249+
250+
251+upd :: t -> PArg' t -> PArg' t
247252upd p' p = p { getTm = p' }
248253
249254-- Check whether function and all descendants cover all cases (partial is
@@ -706,8 +711,10 @@ checkMP ist i mp = if i > 0
706711 | [Partial _] <- lookupTotal f (tt_ctxt ist) = Partial (Other [f])
707712 | otherwise = Unchecked
708713
714+allNothing :: [Maybe a] -> Bool
709715allNothing xs = null (collapseNothing (zip xs [0..]))
710716
717+collapseNothing :: [(Maybe a, b)] -> [(Maybe a, b)]
711718collapseNothing ((Nothing, _) : xs)
712719 = filter (\ (x, _) -> case x of
713720 Nothing -> False
@@ -715,10 +722,12 @@ collapseNothing ((Nothing, _) : xs)
715722collapseNothing (x : xs) = x : collapseNothing xs
716723collapseNothing [] = []
717724
725+noPartial :: [Totality] -> Totality
718726noPartial (Partial p : xs) = Partial p
719727noPartial (_ : xs) = noPartial xs
720728noPartial [] = Total []
721729
730+collapse :: [Totality] -> Totality
722731collapse xs = collapse' Unchecked xs
723732collapse' def (Total r : xs) = Total r
724733collapse' def (Unchecked : xs) = collapse' def xs
src/Idris/Elab/Class.hs+6
@@ -103,11 +103,13 @@ elabClass info syn_in doc fc constraints tn ps pDocs ds
103103 pibind [] x = x
104104 pibind ((n, ty): ns) x = PPi expl n ty (pibind ns x)
105105
106+ mdec :: Name -> Name
106107 mdec (UN n) = SN (MethodN (UN n))
107108 mdec (NS x n) = NS (mdec x) n
108109 mdec x = x
109110
110111 -- TODO: probably should normalise
112+ checkDefaultSuperclassInstance :: PDecl -> Idris ()
111113 checkDefaultSuperclassInstance (PInstance _ fc cs n ps _ _ _)
112114 = do when (not $ null cs) . tclift
113115 $ tfail (At fc (Msg $ "Default superclass instances can't have constraints."))
@@ -118,8 +120,11 @@ elabClass info syn_in doc fc constraints tn ps pDocs ds
118120 $ tfail (At fc (Msg $ "Default instances must be for a superclass constraint on the containing class."))
119121 return ()
120122
123+ impbind :: [(Name, PTerm)] -> PTerm -> PTerm
121124 impbind [] x = x
122125 impbind ((n, ty): ns) x = PPi impl n ty (impbind ns x)
126+
127+ conbind :: [PTerm] -> PTerm -> PTerm
123128 conbind (ty : ns) x = PPi constraint (sMN 0 "class") ty (conbind ns x)
124129 conbind [] x = x
125130
@@ -155,6 +160,7 @@ elabClass info syn_in doc fc constraints tn ps pDocs ds
155160 clause _ = False
156161
157162 -- Generate a function for chasing a dictionary constraint
163+ cfun :: Name -> PTerm -> SyntaxInfo -> [a] -> PTerm -> Idris [PDecl' PTerm]
158164 cfun cn c syn all con
159165 = do let cfn = sUN ('@':'@':show cn ++ "#" ++ show con)
160166 -- SN (ParentN cn (show con))
src/Idris/Elab/Clause.hs+2−2
@@ -180,7 +180,7 @@ elabClauses info fc opts n_in cs = let n = liftname info n_in in
180180 ctxt <- getContext
181181 ist <- getIState
182182 let opt = idris_optimisation ist
183− putIState (ist { idris_patdefs = addDef n (force pdef', force pmissing)
183+ putIState (ist { idris_patdefs = addDef n (force pdef, force pmissing)
184184 (idris_patdefs ist) })
185185 let caseInfo = CaseInfo (inlinable opts) (dictionary opts)
186186 case lookupTy n ctxt of
@@ -600,7 +600,7 @@ elabClause info opts (cnum, PClause fc fname lhs_in withs rhs_in whereblock)
600600 logLvl 6 $ " ==> " ++ show (forget rhs')
601601
602602 (crhs, crhsty) <- if not inf
603− then recheckC_borrowing borrowed fc [] rhs'
603+ then recheckC_borrowing True borrowed fc [] rhs'
604604 else return (rhs', clhsty)
605605 logLvl 6 $ " ==> " ++ show crhsty ++ " against " ++ show clhsty
606606 case converts ctxt [] clhsty crhsty of
src/Idris/Elab/Utils.hs+3−3
@@ -21,12 +21,12 @@ import Debug.Trace
2121
2222import qualified Data.Map as Map
2323
24−recheckC = recheckC_borrowing []
24+recheckC = recheckC_borrowing False []
2525
26−recheckC_borrowing bs fc env t
26+recheckC_borrowing uniq_check bs fc env t
2727 = do -- t' <- applyOpts (forget t) (doesn't work, or speed things up...)
2828 ctxt <- getContext
29− (tm, ty, cs) <- tclift $ case recheck_borrowing bs ctxt env (forget t) t of
29+ (tm, ty, cs) <- tclift $ case recheck_borrowing uniq_check bs ctxt env (forget t) t of
3030 Error e -> tfail (At fc e)
3131 OK x -> return x
3232 addConstraints fc cs
src/Idris/Error.hs+76
@@ -7,17 +7,24 @@ import Idris.AbsSyntax
77import Idris.Delaborate
88import Idris.Output
99
10+import Idris.Core.Evaluate (ctxtAlist)
1011import Idris.Core.TT
1112import Idris.Core.Typecheck
1213import Idris.Core.Constraints
14+import Idris.Output
1315
1416import System.Console.Haskeline
1517import System.Console.Haskeline.MonadException
18+import Control.Monad (when)
1619import Control.Monad.State.Strict
1720import Control.Monad.Error (throwError, catchError)
1821import System.IO.Error(isUserError, ioeGetErrorString)
1922import Data.Char
23+import Data.List (intercalate, isPrefixOf)
24+import qualified Data.Text as T
2025import Data.Typeable
26+import qualified Data.Traversable as Traversable
27+import qualified Data.Foldable as Foldable
2128
2229iucheck :: Idris ()
2330iucheck = do tit <- typeInType
@@ -70,3 +77,72 @@ tctry tc1 tc2
7077getErrSpan :: Err -> FC
7178getErrSpan (At fc _) = fc
7279getErrSpan _ = emptyFC
80+
81+--------------------------------------------------------------------
82+-- Specific warnings not included in elaborator
83+--------------------------------------------------------------------
84+-- | Issue a warning on "with"-terms whose namespace is empty or nonexistent
85+warnDisamb :: IState -> PTerm -> Idris ()
86+warnDisamb ist (PQuote _) = return ()
87+warnDisamb ist (PRef _ _) = return ()
88+warnDisamb ist (PInferRef _ _) = return ()
89+warnDisamb ist (PPatvar _ _) = return ()
90+warnDisamb ist (PLam _ t b) = warnDisamb ist t >> warnDisamb ist b
91+warnDisamb ist (PPi _ _ t b) = warnDisamb ist t >> warnDisamb ist b
92+warnDisamb ist (PLet _ x t b) = warnDisamb ist x >> warnDisamb ist t >> warnDisamb ist b
93+warnDisamb ist (PTyped x t) = warnDisamb ist x >> warnDisamb ist t
94+warnDisamb ist (PApp _ t args) = warnDisamb ist t >>
95+ mapM_ (warnDisamb ist . getTm) args
96+warnDisamb ist (PAppBind _ f args) = warnDisamb ist f >>
97+ mapM_ (warnDisamb ist . getTm) args
98+warnDisamb ist (PMatchApp _ _) = return ()
99+warnDisamb ist (PCase _ tm cases) = warnDisamb ist tm >>
100+ mapM_ (\(x,y)-> warnDisamb ist x >> warnDisamb ist y) cases
101+warnDisamb ist (PTrue _ _) = return ()
102+warnDisamb ist (PFalse _) = return ()
103+warnDisamb ist (PRefl _ tm) = warnDisamb ist tm
104+warnDisamb ist (PResolveTC _) = return ()
105+warnDisamb ist (PEq _ a b x y) = warnDisamb ist a >> warnDisamb ist b >>
106+ warnDisamb ist x >> warnDisamb ist y
107+warnDisamb ist (PRewrite _ x y z) = warnDisamb ist x >> warnDisamb ist y >>
108+ Foldable.mapM_ (warnDisamb ist) z
109+warnDisamb ist (PPair _ _ x y) = warnDisamb ist x >> warnDisamb ist y
110+warnDisamb ist (PDPair _ _ x y z) = warnDisamb ist x >> warnDisamb ist y >> warnDisamb ist z
111+warnDisamb ist (PAlternative _ tms) = mapM_ (warnDisamb ist) tms
112+warnDisamb ist (PHidden tm) = warnDisamb ist tm
113+warnDisamb ist PType = return ()
114+warnDisamb ist (PUniverse _) = return ()
115+warnDisamb ist (PGoal _ x _ y) = warnDisamb ist x >> warnDisamb ist y
116+warnDisamb ist (PConstant _) = return ()
117+warnDisamb ist Placeholder = return ()
118+warnDisamb ist (PDoBlock steps) = mapM_ wStep steps
119+ where wStep (DoExp _ x) = warnDisamb ist x
120+ wStep (DoBind _ _ x) = warnDisamb ist x
121+ wStep (DoBindP _ x y cs) = warnDisamb ist x >> warnDisamb ist y >>
122+ mapM_ (\(x,y)-> warnDisamb ist x >> warnDisamb ist y) cs
123+ wStep (DoLet _ _ x y) = warnDisamb ist x >> warnDisamb ist y
124+ wStep (DoLetP _ x y) = warnDisamb ist x >> warnDisamb ist y
125+warnDisamb ist (PIdiom _ x) = warnDisamb ist x
126+warnDisamb ist (PReturn _) = return ()
127+warnDisamb ist (PMetavar _) = return ()
128+warnDisamb ist (PProof tacs) = mapM_ (Foldable.mapM_ (warnDisamb ist)) tacs
129+warnDisamb ist (PTactics tacs) = mapM_ (Foldable.mapM_ (warnDisamb ist)) tacs
130+warnDisamb ist (PElabError _) = return ()
131+warnDisamb ist PImpossible = return ()
132+warnDisamb ist (PCoerced tm) = warnDisamb ist tm
133+warnDisamb ist (PDisamb ds tm) = warnDisamb ist tm >>
134+ mapM_ warnEmpty ds
135+ where warnEmpty d =
136+ when (null (filter (isIn d . fst) (ctxtAlist (tt_ctxt ist)))) $
137+ ierror . Msg $
138+ "Nothing found in namespace \"" ++
139+ intercalate "." (map T.unpack d) ++
140+ "\"."
141+ isIn d (NS _ ns) = isPrefixOf d ns
142+ isIn d _ = False
143+
144+warnDisamb ist (PUnifyLog tm) = warnDisamb ist tm
145+warnDisamb ist (PNoImplicits tm) = warnDisamb ist tm
146+warnDisamb ist (PQuasiquote tm goal) = warnDisamb ist tm >>
147+ Foldable.mapM_ (warnDisamb ist) goal
148+warnDisamb ist (PUnquote tm) = warnDisamb ist tm
src/Idris/Help.hs+2−1
@@ -69,7 +69,8 @@ help =
6969 ([":q",":quit"], NoArg, "Exit the Idris system"),
7070 ([":w", ":warranty"], NoArg, "Displays warranty information"),
7171 ([":let"], ManyArgs DeclArg, "Evaluate a declaration, such as a function definition, instance implementation, or fixity declaration"),
72− ([":undefine",":unlet"], ManyArgs NameArg, "Remove the listed repl definitions, or all repl definitions if no names given")
72+ ([":undefine",":unlet"], ManyArgs NameArg, "Remove the listed repl definitions, or all repl definitions if no names given"),
73+ ([":printdef"], NameArg, "Show the definition of a function")
7374 ]
7475
7576-- | Use these for completion, but don't show them in :help
src/Idris/PartialEval.hs+2
@@ -86,6 +86,7 @@ mkPE_TyDecl ist args ty = mkty args ty
8686 mkty [] t = delab ist t
8787
8888-- | Checks if a given argument is a type class constraint argument
89+classConstraint :: Idris.AbsSyntax.IState -> TT Name -> Bool
8990classConstraint ist v
9091 | (P _ c _, args) <- unApply v = case lookupCtxt c (idris_classes ist) of
9192 [_] -> True
@@ -94,6 +95,7 @@ classConstraint ist v
9495
9596-- | Checks if the given arguments of a type class constraint are all either constants
9697-- or references (i.e. that it doesn't contain any complex terms).
98+concreteClass :: IState -> TT Name -> Bool
9799concreteClass ist v
98100 | not (classConstraint ist v) = False
99101 | (P _ c _, args) <- unApply v = all concrete args
src/Idris/Providers.hs+5−2
@@ -7,15 +7,18 @@ import Idris.AbsSyntax
77import Idris.AbsSyntaxTree
88import Idris.Error
99
10−import Debug.Trace
11−
1210-- | Wrap a type provider in the type of type providers
1311providerTy :: FC -> PTerm -> PTerm
1412providerTy fc tm
1513 = PApp fc (PRef fc $ sUN "Provider") [PExp 0 [] (sMN 0 "pvarg") tm]
1614
15+ioret :: Name
1716ioret = sUN "prim_io_return"
17+
18+ermod :: Name
1819ermod = sNS (sUN "Error") ["Providers"]
20+
21+prmod :: Name
1922prmod = sNS (sUN "Provide") ["Providers"]
2023
2124data Provided a = Provide a
src/Idris/REPL.hs+24
@@ -511,6 +511,7 @@ ideslaveProcess fn (ChangeDirectory f) = do process fn (ChangeDirectory f)
511511ideslaveProcess fn (Eval t) = process fn (Eval t)
512512ideslaveProcess fn (NewDefn decls) = do process fn (NewDefn decls)
513513 iPrintResult "defined"
514+ideslaveProcess fn (Undefine n) = process fn (Undefine n)
514515ideslaveProcess fn (ExecVal t) = process fn (ExecVal t)
515516ideslaveProcess fn (Check (PRef x n)) = process fn (Check (PRef x n))
516517ideslaveProcess fn (Check t) = process fn (Check t)
@@ -568,6 +569,7 @@ ideslaveProcess fn (Apropos a) = do process fn (Apropos a)
568569 iPrintResult ""
569570ideslaveProcess fn (WhoCalls n) = process fn (WhoCalls n)
570571ideslaveProcess fn (CallsWho n) = process fn (CallsWho n)
572+ideslaveProcess fn (PrintDef n) = process fn (PrintDef n)
571573ideslaveProcess fn _ = iPrintError "command not recognized or not supported"
572574
573575
@@ -689,6 +691,7 @@ process fn (ChangeDirectory f)
689691 return ()
690692process fn (Eval t)
691693 = withErrorReflection $ do logLvl 5 $ show t
694+ getIState >>= flip warnDisamb t
692695 (tm, ty) <- elabVal recinfo ERHS t
693696 ctxt <- getContext
694697 let tm' = force (normaliseAll ctxt [] tm)
@@ -1170,6 +1173,27 @@ process fn (MakeDoc s) =
11701173 else return . Left $ "Illegal name: " ++ head bad
11711174 case result of Right _ -> iputStrLn "IdrisDoc generated"
11721175 Left err -> iPrintError err
1176+process fn (PrintDef n) =
1177+ do ist <- getIState
1178+ let patdefs = idris_patdefs ist
1179+ result = map (ppDef ist) (lookupCtxtName n patdefs)
1180+ case result of
1181+ [] -> iPrintError "Not found"
1182+ outs -> iRenderResult . vsep $ outs
1183+ where ppDef :: IState -> (Name, ([([Name], Term, Term)], [PTerm])) -> Doc OutputAnnotation
1184+ ppDef ist (n, (clauses, missing)) =
1185+ prettyName True True [] n <+> colon <+>
1186+ pprintPTerm (ppOptionIst ist) [] [] [] (delabTy ist n) <$>
1187+ indent 2 (ppClauses ist clauses <> ppMissing missing)
1188+ ppClauses ist [] = text "No clauses."
1189+ ppClauses ist cs = vsep (map pp cs)
1190+ where pp (vars, lhs, rhs) =
1191+ let ppTm = pprintPTerm (ppOptionIst ist)
1192+ (zip vars (repeat False))
1193+ [] [] .
1194+ delab ist
1195+ in ppTm lhs <+> text "=" <+> ppTm rhs
1196+ ppMissing _ = empty
11731197
11741198
11751199showTotal :: Totality -> IState -> String
src/Idris/REPLParser.hs+1
@@ -133,6 +133,7 @@ pCmd = do P.whiteSpace; do cmd ["q", "quit"]; eof; return Quit
133133 <|> do cmd ["wc", "whocalls"]; P.whiteSpace; n <- P.fnName ; return (WhoCalls n)
134134 <|> do cmd ["cw", "callswho"]; P.whiteSpace; n <- P.fnName ; return (CallsWho n)
135135 <|> do cmd ["mkdoc"]; str <- many anyChar; return (MakeDoc str)
136+ <|> do cmd ["printdef"]; P.whiteSpace; n <- P.fnName; return (PrintDef n)
136137 <|> do P.whiteSpace; do eof; return NOP
137138 <|> do t <- P.fullExpr defaultSyntax; return (Eval t)
138139
src/Idris/TypeSearch.hs+210−139
@@ -4,11 +4,11 @@ module Idris.TypeSearch (
44 searchByType, searchPred, defaultScoreFunction
55) where
66
7−import Control.Applicative ((<$>), (<*>), (<|>))
8−import Control.Arrow (first, second, (&&&))
9−import Control.Monad (forM_, guard)
7+import Control.Applicative (Applicative (..), (<$>), (<*>), (<|>))
8+import Control.Arrow (first, second, (&&&), (***))
9+import Control.Monad (guard)
1010
11−import Data.List (find, delete, deleteBy, minimumBy, partition, sortBy, (\\))
11+import Data.List (find, partition, (\\))
1212import Data.Map (Map)
1313import qualified Data.Map as M
1414import Data.Maybe (catMaybes, fromMaybe, isJust, maybeToList, mapMaybe)
@@ -18,11 +18,12 @@ import qualified Data.PriorityQueue.FingerTree as Q
1818import Data.Set (Set)
1919import qualified Data.Set as S
2020import qualified Data.Text as T (pack, isPrefixOf)
21+import Data.Traversable (traverse)
2122
22−import Idris.AbsSyntax (addUsingConstraints, addImpl, getContext, getIState, putIState, implicit)
23−import Idris.AbsSyntaxTree (class_instances, ClassInfo, defaultSyntax, Idris,
23+import Idris.AbsSyntax (addUsingConstraints, addImpl, getIState, putIState, implicit)
24+import Idris.AbsSyntaxTree (class_instances, ClassInfo, defaultSyntax, eqTy, Idris,
2425 IState (idris_classes, idris_docstrings, tt_ctxt, idris_outputmode),
25− implicitAllowed, OutputMode(..), prettyDocumentedIst, prettyIst, PTerm, toplevel)
26+ implicitAllowed, OutputMode(..), prettyDocumentedIst, PTerm, toplevel)
2627import Idris.Core.Evaluate (Context (definitions), Def (Function, TyDecl, CaseOp), normaliseC)
2728import Idris.Core.TT hiding (score)
2829import Idris.Core.Unify (match_unify)
@@ -31,30 +32,32 @@ import Idris.Docstrings (noDocs, overview)
3132import Idris.Elab.Type (elabType)
3233import Idris.Output (iRenderOutput, iPrintResult, iRenderResult)
3334
35+import Prelude hiding (pred)
36+
3437import Util.Pretty (text, char, vsep, (<>), Doc)
3538
3639searchByType :: PTerm -> Idris ()
3740searchByType pterm = do
3841 pterm' <- addUsingConstraints syn emptyFC pterm
39− pterm'' <- implicit toplevel syn n pterm'
42+ pterm'' <- implicit toplevel syn name pterm'
4043 i <- getIState
4144 let pterm''' = addImpl i pterm''
42− ty <- elabType toplevel syn (fst noDocs) (snd noDocs) emptyFC [] n pterm'
45+ ty <- elabType toplevel syn (fst noDocs) (snd noDocs) emptyFC [] name pterm'
4346 putIState i -- don't actually make any changes
4447 let names = searchUsing searchPred i ty
45− let names' = take numLimit $ names
48+ let names' = take numLimit names
4649 let docs =
4750 [ let docInfo = (n, delabTy i n, fmap (overview . fst) (lookupCtxtExact n (idris_docstrings i))) in
48− displayScore score <> char ' ' <> prettyDocumentedIst i docInfo
49− | (n, score) <- names']
51+ displayScore theScore <> char ' ' <> prettyDocumentedIst i docInfo
52+ | (n, theScore) <- names']
5053 case idris_outputmode i of
5154 RawOutput _ -> do mapM_ iRenderOutput docs
5255 iPrintResult ""
53− IdeSlave n h -> iRenderResult (vsep docs)
56+ IdeSlave _ _ -> iRenderResult (vsep docs)
5457 where
5558 numLimit = 50
5659 syn = defaultSyntax { implicitAllowed = True } -- syntax
57− n = sMN 0 "searchType" -- name
60+ name = sMN 0 "searchType" -- name
5861
5962-- | Conduct a type-directed search using a given match predicate
6063searchUsing :: (IState -> Type -> [(Name, Type)] -> [(Name, a)])
@@ -69,7 +72,7 @@ searchUsing pred istate ty = pred istate nty . concat . M.elems $
6972 type2 <- typeFromDef x
7073 return $ normaliseC ctxt [] type2
7174 special :: Name -> Bool
72− special (NS n ns) = special n
75+ special (NS n _) = special n
7376 special (SN _) = True
7477 special (UN n) = T.pack "default#" `T.isPrefixOf` n
7578 || n `elem` map T.pack ["believe_me", "really_believe_me"]
@@ -85,7 +88,7 @@ searchPred istate ty1 = matcher where
8588typeFromDef :: (Def, b, c, d) -> Maybe Type
8689typeFromDef (def, _, _, _) = get def where
8790 get :: Def -> Maybe Type
88− get (Function ty tm) = Just ty
91+ get (Function ty _) = Just ty
8992 get (TyDecl _ ty) = Just ty
9093 -- get (Operator ty _ _) = Just ty
9194 get (CaseOp _ ty _ _ _ _) = Just ty
@@ -106,17 +109,17 @@ computeDagP :: Ord n
106109 => (TT n -> Bool) -- ^ filter to remove some arguments
107110 -> TT n
108111 -> ([((n, TT n), Set n)], [(n, TT n)], TT n)
109−computeDagP removePred t = (reverse (map f args), reverse removedArgs , retTy) where
110− f (n, t) = ((n, t), M.keysSet (usedVars t))
112+computeDagP removePred t = (reverse (map f arguments), reverse theRemovedArgs , retTy) where
113+ f (n, ty) = ((n, ty), M.keysSet (usedVars ty))
111114
112− (numArgs, args, removedArgs, retTy) = go 0 [] [] t
115+ (arguments, theRemovedArgs, retTy) = go [] [] t
113116
114117 -- NOTE : args are in reverse order
115− go k args removedArgs (Bind n (Pi t _) sc) = let arg = (n, t) in
116− if removePred t
117− then go k args (arg : removedArgs) sc
118− else go (succ k) (arg : args) removedArgs sc
119− go k args removedArgs retTy = (k, args, removedArgs, retTy)
118+ go args removedArgs (Bind n (Pi ty _) sc) = let arg = (n, ty) in
119+ if removePred ty
120+ then go args (arg : removedArgs) sc
121+ else go (arg : args) removedArgs sc
122+ go args removedArgs sc = (args, removedArgs, sc)
120123
121124-- | Collect the names and types of all the free variables
122125-- The Boolean indicates those variables which are determined due to injectivity
@@ -130,7 +133,7 @@ usedVars = f True where
130133 bind -> f b (binderTy bind)
131134 f b (App t1 t2) = f b t1 `M.union` f (b && isInjective t1) t2
132135 f b (Proj t _) = f b t
133− f _ (V j) = error "unexpected! run vToP first"
136+ f _ (V _) = error "unexpected! run vToP first"
134137 f _ _ = M.empty
135138
136139-- | Remove a node from a directed acyclic graph
@@ -143,73 +146,102 @@ deleteFromDag name (((name2, ty), (ix, set)) : xs) = (if name == name2
143146deleteFromArgList :: Ord n => n -> [(n, TT n)] -> [(n, TT n)]
144147deleteFromArgList n = filter ((/= n) . fst)
145148
149+-- | Asymmetric modifications to keep track of
150+data AsymMods = Mods
151+ { argApp :: !Int
152+ , typeClassApp :: !Int
153+ , typeClassIntro :: !Int
154+ } deriving (Eq, Show)
155+
156+
157+-- | Homogenous tuples
158+data Sided a = Sided
159+ { left :: !a
160+ , right :: !a
161+ } deriving (Eq, Show)
162+
163+sided :: (a -> a -> b) -> Sided a -> b
164+sided f (Sided l r) = f l r
165+
166+-- | Could be a functor instance, but let's avoid name overloading
167+both :: (a -> b) -> Sided a -> Sided b
168+both f (Sided l r) = Sided (f l) (f r)
169+
146170data Score = Score
147− { transposition :: !Int
148− , leftApplied :: !Int
149− , rightApplied :: !Int
150− , leftTypeClassApp :: !Int
151− , rightTypeClassApp :: !Int
152− , leftTypeClassIntro :: !Int
153− , rightTypeClassIntro :: !Int } deriving (Eq, Show)
171+ { transposition :: !Int
172+ , equalityFlips :: !Int
173+ , asymMods :: !(Sided AsymMods)
174+ } deriving (Eq, Show)
154175
155176displayScore :: Score -> Doc a
156−displayScore (Score trans lapp rapp lclassapp rclassapp lclassintro rclassintro) = text $ case (lt, gt) of
157− (True , True ) -> "=" -- types are isomorphic
158− (True , False) -> "<" -- found type is more general than searched type
159− (False, True ) -> ">" -- searched type is more general than found type
160− (False, False) -> "_"
161− where lt = lapp + lclassapp + lclassintro == 0
162− gt = rapp + rclassapp + rclassintro == 0
163−
177+displayScore score = text $ case both noMods (asymMods score) of
178+ Sided True True -> "=" -- types are isomorphic
179+ Sided True False -> "<" -- found type is more general than searched type
180+ Sided False True -> ">" -- searched type is more general than found type
181+ Sided False False -> "_"
182+ where
183+ noMods (Mods app tcApp tcIntro) = app + tcApp + tcIntro == 0
164184
165185scoreCriterion :: Score -> Bool
166−scoreCriterion (Score a b c d e f g) = not
167− ( (b > 0 && c > 0) || (b + c) > 4 || any (> 3) [d,e,f,g])
186+scoreCriterion (Score _ _ amods) = not
187+ ( sided (&&) (both ((> 0) . argApp) amods)
188+ || sided (+) (both argApp amods) > 4
189+ || sided (||) (both (\(Mods _ tcApp tcIntro) -> tcApp > 3 || tcIntro > 3) amods)
190+ )
168191
169192defaultScoreFunction :: Score -> Int
170−defaultScoreFunction (Score a b c d e f g) = a + 9*b + 3*c + 12*d + 4*e + 6*f + 2*g + 100*(2*b + d + f)*(2*c + e + g)
193+defaultScoreFunction (Score trans eqFlip amods) =
194+ trans + eqFlip + linearPenalty + upAndDowncastPenalty
195+ where
196+ -- prefer finding a more general type to a less general type
197+ linearPenalty = (\(Sided l r) -> 3 * l + r)
198+ (both (\(Mods app tcApp tcIntro) -> 3 * app + 4 * tcApp + 2 * tcIntro) amods)
171199 -- it's very bad to have *both* upcasting and downcasting
200+ upAndDowncastPenalty = 100 *
201+ sided (*) (both (\(Mods app tcApp tcIntro) -> 2 * app + tcApp + tcIntro) amods)
202+
203+instance Monoid a => Monoid (Sided a) where
204+ mempty = Sided mempty mempty
205+ (Sided l1 r1) `mappend` (Sided l2 r2) = Sided (l1 `mappend` l2) (r1 `mappend` r2)
206+
207+instance Monoid AsymMods where
208+ mempty = Mods 0 0 0
209+ (Mods a b c) `mappend` (Mods a' b' c') = Mods (a + a') (b + b') (c + c')
172210
173211instance Monoid Score where
174− mempty = Score 0 0 0 0 0 0 0
175− (Score a b c d e f g) `mappend` (Score a' b' c' d' e' f' g') =
176− Score (a + a') (b + b') (c + c') (d + d') (e + e') (f + f') (g + g')
212+ mempty = Score 0 0 mempty
213+ (Score t e mods) `mappend` (Score t' e' mods') = Score (t + t') (e + e') (mods `mappend` mods')
177214
178215-- | A directed acyclic graph representing the arguments to a function
179216-- The 'Int' represents the position of the argument (1st argument, 2nd, etc.)
180217type ArgsDAG = [((Name, Type), (Int, Set Name))]
181218
219+-- | A list of typeclass constraints
220+type Classes = [(Name, Type)]
221+
182222-- | The state corresponding to an attempted match of two types.
183223data State = State
184− { holes :: ![(Name, Type)] -- ^ names which have yet to be resolved
185− , args1 :: !ArgsDAG -- ^ arguments for the left type which have yet to be resolved
186− , args2 :: !ArgsDAG -- ^ arguments for the right type which have yet to be resolved
187− , classes1 :: ![(Name, Type)] -- ^ typeclass arguments for the left type which haven't been resolved
188− , classes2 :: ![(Name, Type)] -- ^ typeclass arguments for the right type which haven't been resolved
224+ { holes :: ![(Name, Type)] -- ^ names which have yet to be resolved
225+ , argsAndClasses :: !(Sided (ArgsDAG, Classes))
226+ -- ^ arguments and typeclass constraints for each type which have yet to be resolved
189227 , score :: !Score -- ^ the score so far
190228 , usedNames :: ![Name] -- ^ all names that have been used
191229 } deriving Show
192230
193−modifyTypes :: (Type -> Type) -> State -> State
194−modifyTypes f (State h a1 a2 c1 c2 s un) =
195− State h (modifyDag a1) (modifyDag a2)
196− (modifyList c1) (modifyList c2)
197− s un
231+modifyTypes :: (Type -> Type) -> (ArgsDAG, Classes) -> (ArgsDAG, Classes)
232+modifyTypes f = modifyDag *** modifyList
198233 where
199234 modifyDag = map (first (second f))
200235 modifyList = map (second f)
201236
202237findNameInArgsDAG :: Name -> ArgsDAG -> Maybe (Type, Maybe Int)
203−findNameInArgsDAG name xs = fmap ((snd . fst) &&& (Just . fst . snd)) . find ((name ==) . fst . fst) $ xs
204−
205−findLeft, findRight :: Name -> State -> Maybe (Type, Maybe Int)
206−findLeft n (State _ a1 a2 c1 c2 _ _) = findNameInArgsDAG n a1 <|> ((,) <$> lookup n c1 <*> Nothing)
207−findRight n (State _ a1 a2 c1 c2 _ _) = findNameInArgsDAG n a2 <|> ((,) <$> lookup n c2 <*> Nothing)
238+findNameInArgsDAG name = fmap ((snd . fst) &&& (Just . fst . snd)) . find ((name ==) . fst . fst)
208239
209−deleteLeft, deleteRight :: Name -> State -> State
210−deleteLeft n state = state { args1 = deleteFromDag n (args1 state) , classes1 = filter ((/= n) . fst) (classes1 state) }
211−deleteRight n state = state { args2 = deleteFromDag n (args2 state) , classes2 = filter ((/= n) . fst) (classes2 state) }
240+findName :: Name -> (ArgsDAG, Classes) -> Maybe (Type, Maybe Int)
241+findName n (args, classes) = findNameInArgsDAG n args <|> ((,) <$> lookup n classes <*> Nothing)
212242
243+deleteName :: Name -> (ArgsDAG, Classes) -> (ArgsDAG, Classes)
244+deleteName n (args, classes) = (deleteFromDag n args, filter ((/= n) . fst) classes)
213245
214246tcToMaybe :: TC' e a -> Maybe a
215247tcToMaybe (OK x) = Just x
@@ -221,13 +253,13 @@ inArgTys = map . first . second
221253
222254typeclassUnify :: Ctxt ClassInfo -> Context -> Type -> Type -> Maybe [(Name, Type)]
223255typeclassUnify classInfo ctxt ty tyTry = do
224− res <- tcToMaybe $ match_unify ctxt [] ty retTy [] holes []
225− guard $ null (holes \\ map fst res)
256+ res <- tcToMaybe $ match_unify ctxt [] ty retTy [] theHoles []
257+ guard $ null (theHoles \\ map fst res)
226258 let argTys' = map (second $ foldr (.) id [ subst n t | (n, t) <- res ]) tcArgs
227259 return argTys'
228260 where
229261 tyTry' = vToP tyTry
230− holes = map fst nonTcArgs
262+ theHoles = map fst nonTcArgs
231263 retTy = getRetTy tyTry'
232264 (tcArgs, nonTcArgs) = partition (isTypeClassArg classInfo . snd) $ getArgTys tyTry'
233265
@@ -247,30 +279,53 @@ subsets [] = [[]]
247279subsets (x : xs) = let ss = subsets xs in map (x :) ss ++ ss
248280
249281
282+-- not recursive (i.e., doesn't flip iterated identities) at the moment
283+-- recalls the number of flips that have been made
284+flipEqualities :: Type -> [(Int, Type)]
285+flipEqualities t = case t of
286+ eq1@(App (App (App (App eq@(P _ eqty _) tyL) tyR) valL) valR) | eqty == eqTy ->
287+ [(0, eq1), (1, App (App (App (App eq tyR) tyL) valR) valL)]
288+ Bind n binder sc -> (\bind' (j, sc') -> (fst (binderTy bind') + j, Bind n (fmap snd bind') sc'))
289+ <$> traverse flipEqualities binder <*> flipEqualities sc
290+ App f x -> (\(i, f') (j, x') -> (i + j, App f' x'))
291+ <$> flipEqualities f <*> flipEqualities x
292+ t' -> [(0, t')]
293+
250294--DONT run vToP first!
251295-- | Try to match two types together in a unification-like procedure.
252296-- Returns a list of types and their minimum scores, sorted in order
253297-- of increasing score.
254298matchTypesBulk :: forall info. IState -> Int -> Type -> [(info, Type)] -> [(info, Score)]
255299matchTypesBulk istate maxScore type1 types = getAllResults startQueueOfQueues where
256− getStartQueue :: (info, Type) -> Maybe (Score, (info, Q.PQueue Score State))
257− getStartQueue nty@(info, type2) = do
258− state <- unifyQueue (State startingHoles dag1 dag2
259− typeClassArgs1 typeClassArgs2
260− mempty usedNames) startingTypes
261− let sc = score state
262− return $ (sc, (info, Q.singleton sc state))
300+ getStartQueues :: (info, Type) -> Maybe (Score, (info, Q.PQueue Score State))
301+ getStartQueues nty@(info, type2) = case mapMaybe startStates ty2s of
302+ [] -> Nothing
303+ xs -> Just (minimum (map fst xs), (info, Q.fromList xs))
263304 where
305+ ty2s = (\(i, dag) (j, retTy) -> (i + j, dag, retTy))
306+ <$> flipEqualitiesDag dag2 <*> flipEqualities retTy2
307+ flipEqualitiesDag dag = case dag of
308+ [] -> [(0, [])]
309+ ((n, ty), (pos, deps)) : xs ->
310+ (\(i, ty') (j, xs') -> (i + j , ((n, ty'), (pos, deps)) : xs'))
311+ <$> flipEqualities ty <*> flipEqualitiesDag xs
312+ startStates (numEqFlips, sndDag, sndRetTy) = do
313+ state <- unifyQueue (State startingHoles
314+ (Sided (dag1, typeClassArgs1) (sndDag, typeClassArgs2))
315+ (mempty { equalityFlips = numEqFlips }) usedns) [(retTy1, sndRetTy)]
316+ return (score state, state)
317+
318+
264319 (dag2, typeClassArgs2, retTy2) = makeDag (uniqueBinders (map fst argNames1) type2)
265320 argNames2 = map fst dag2
266− usedNames = map fst (argNames1 ++ argNames2)
321+ usedns = map fst startingHoles
267322 startingHoles = argNames1 ++ argNames2
268323
269− startingTypes = (retTy1, retTy2) : []
324+ startingTypes = [(retTy1, retTy2)]
270325
271326
272327 startQueueOfQueues :: Q.PQueue Score (info, Q.PQueue Score State)
273− startQueueOfQueues = Q.fromList $ mapMaybe getStartQueue types
328+ startQueueOfQueues = Q.fromList $ mapMaybe getStartQueues types
274329
275330 getAllResults :: Q.PQueue Score (info, Q.PQueue Score State) -> [(info, Score)]
276331 getAllResults q = case Q.minViewWithKey q of
@@ -282,7 +337,7 @@ matchTypesBulk istate maxScore type1 types = getAllResults startQueueOfQueues wh
282337 Just (Left stateQ') -> case Q.minViewWithKey stateQ' of
283338 Nothing -> getAllResults q'
284339 Just ((newQscore,_), _) -> getAllResults (Q.add newQscore (info, stateQ') q')
285− Just (Right score) -> (info, score) : getAllResults q'
340+ Just (Right theScore) -> (info, theScore) : getAllResults q'
286341 else []
287342
288343
@@ -291,7 +346,7 @@ matchTypesBulk istate maxScore type1 types = getAllResults startQueueOfQueues wh
291346
292347 (dag1, typeClassArgs1, retTy1) = makeDag type1
293348 argNames1 = map fst dag1
294− makeDag :: Type -> (ArgsDAG, [(Name, Type)], Type)
349+ makeDag :: Type -> (ArgsDAG, Classes, Type)
295350 makeDag = first3 (zipWith (\i (ty, deps) -> (ty, (i, deps))) [0..] . reverseDag) .
296351 computeDagP (isTypeClassArg classInfo) . vToP
297352 first3 f (a,b,c) = (f a, b, c)
@@ -300,44 +355,45 @@ matchTypesBulk istate maxScore type1 types = getAllResults startQueueOfQueues wh
300355 resolveUnis :: [(Name, Type)] -> State -> Maybe (State, [(Type, Type)])
301356 resolveUnis [] state = Just (state, [])
302357 resolveUnis ((name, term@(P Bound name2 _)) : xs)
303− state@(State holes args1 args2 _ _ _ _) | isJust findArgs = do
358+ state | isJust findArgs = do
304359 ((ty1, ix1), (ty2, ix2)) <- findArgs
305360
306361 (state'', queue) <- resolveUnis xs state'
307362 let transScore = fromMaybe 0 (abs <$> ((-) <$> ix1 <*> ix2))
308− return $ (inScore (\s -> s { transposition = transposition s + transScore }) state'', (ty1, ty2) : queue)
363+ return (inScore (\s -> s { transposition = transposition s + transScore }) state'', (ty1, ty2) : queue)
309364 where
310− mgetType name xs = fmap ((snd . fst) &&& (fst . snd)) . find ((name ==) . fst . fst) $ xs
311− inScore f state = state { score = f (score state) }
312− findArgs = ((,) <$> findLeft name state <*> findRight name2 state) <|>
313− ((,) <$> findLeft name2 state <*> findRight name state)
365+ unresolved = argsAndClasses state
366+ inScore f stat = stat { score = f (score stat) }
367+ findArgs = ((,) <$> findName name (left unresolved) <*> findName name2 (right unresolved)) <|>
368+ ((,) <$> findName name2 (left unresolved) <*> findName name (right unresolved))
314369 matchnames = [name, name2]
315− holes' = filter (not . (`elem` matchnames) . fst) holes
316− deleteArgs = deleteLeft name . deleteLeft name2 . deleteRight name . deleteRight name2
317− state' = modifyTypes (subst name term) $ deleteArgs
318− (state { holes = holes'})
370+ deleteArgs = deleteName name . deleteName name2
371+ state' = state { holes = filter (not . (`elem` matchnames) . fst) (holes state)
372+ , argsAndClasses = both (modifyTypes (subst name term) . deleteArgs) unresolved}
319373
320374 resolveUnis ((name, term) : xs)
321− state@(State holes args1 args2 _ _ _ _) = case (findLeft name state, findRight name state) of
322− (Just (_,ix), Nothing) -> first (addScore (mempty { leftApplied = 1, rightApplied = otherApplied})) <$> nextStep
323− (Nothing, Just (_,ix)) -> first (addScore (mempty { rightApplied = 1, leftApplied = otherApplied})) <$> nextStep
324− (Nothing, Nothing) -> nextStep
325− _ -> error ("Idris internal error: TypeSearch.resolveUnis")
375+ state@(State hs unresolved _ _) = case both (findName name) unresolved of
376+ Sided Nothing Nothing -> Nothing
377+ Sided (Just _) (Just _) -> error "Idris internal error: TypeSearch.resolveUnis"
378+ oneOfEach -> first (addScore (both scoreFor oneOfEach)) <$> nextStep
326379 where
380+ scoreFor (Just _) = mempty { argApp = 1 }
381+ scoreFor Nothing = mempty { argApp = otherApplied }
327382 -- find variables which are determined uniquely by the type
328383 -- due to injectivity
329384 matchedVarMap = usedVars term
330− both f (x, y) = (f x, f y)
331− (injUsedVars, notInjUsedVars) = both M.keys . M.partition id . M.filterWithKey (\k _-> k `elem` map fst holes) $ M.map snd matchedVarMap
385+ bothT f (x, y) = (f x, f y)
386+ (injUsedVars, notInjUsedVars) = bothT M.keys . M.partition id . M.filterWithKey (\k _-> k `elem` map fst hs) $ M.map snd matchedVarMap
332387 varsInTy = injUsedVars ++ notInjUsedVars
333388 toDelete = name : varsInTy
334− deleteMany = foldr (.) id $ [ deleteLeft t . deleteRight t | t <- toDelete ]
389+ deleteMany = foldr (.) id (map deleteName toDelete)
335390
336391 otherApplied = length notInjUsedVars
337392
338− addScore additions state = state { score = score state `mappend` additions }
339− state' = modifyTypes (subst name term) . deleteMany $
340− state { holes = filter (not . (`elem` toDelete) . fst) holes }
393+ addScore additions theState = theState { score = let s = score theState in
394+ s { asymMods = asymMods s `mappend` additions } }
395+ state' = state { holes = filter (not . (`elem` toDelete) . fst) hs
396+ , argsAndClasses = both (modifyTypes (subst name term) . deleteMany) (argsAndClasses state) }
341397 nextStep = resolveUnis xs state'
342398
343399
@@ -352,13 +408,13 @@ matchTypesBulk istate maxScore type1 types = getAllResults startQueueOfQueues wh
352408 unifyQueue state' (queue ++ queueAdditions)
353409
354410 possClassInstances :: [Name] -> Type -> [Type]
355− possClassInstances usedNames ty = do
411+ possClassInstances usedns ty = do
356412 className <- getClassName clss
357413 classDef <- lookupCtxt className classInfo
358414 n <- class_instances classDef
359415 def <- lookupCtxt n (definitions ctxt)
360− ty <- normaliseC ctxt [] <$> (case typeFromDef def of Just x -> [x]; Nothing -> [])
361− let ty' = vToP (uniqueBinders usedNames ty)
416+ nty <- normaliseC ctxt [] <$> (case typeFromDef def of Just x -> [x]; Nothing -> [])
417+ let ty' = vToP (uniqueBinders usedns nty)
362418 return ty'
363419 where
364420 (clss, _) = unApply ty
@@ -377,7 +433,7 @@ matchTypesBulk istate maxScore type1 types = getAllResults startQueueOfQueues wh
377433 else Q.empty in
378434 Just $ Left (Q.union rest additions)
379435 where
380− isFinal (State [] [] [] [] [] score _) = True
436+ isFinal (State [] (Sided ([], []) ([], [])) _ _) = True
381437 isFinal _ = False
382438
383439 -- | Find all possible matches starting from a given state.
@@ -386,36 +442,40 @@ matchTypesBulk istate maxScore type1 types = getAllResults startQueueOfQueues wh
386442 nextSteps :: State -> [State]
387443
388444 -- Stage 3 - match typeclasses
389− nextSteps (State [] [] [] c1 c2 scoreAcc usedNames) =
445+ nextSteps (State [] unresolved@(Sided ([], c1) ([], c2)) scoreAcc usedns) =
390446 if null results3 then results4 else results3
391447 where
392448 -- try to match a typeclass argument from the left with a typeclass argument from the right
393449 results3 =
394− catMaybes [ unifyQueue (State [] [] []
395− (deleteFromArgList n1 c1) (map (second subst2for1) (deleteFromArgList n2 c2)) scoreAcc usedNames) [(ty1, ty2)]
450+ catMaybes [ unifyQueue (State []
451+ (Sided ([], deleteFromArgList n1 c1)
452+ ([], map (second subst2for1) (deleteFromArgList n2 c2)))
453+ scoreAcc usedns) [(ty1, ty2)]
396454 | (n1, ty1) <- c1, (n2, ty2) <- c2, let subst2for1 = psubst n2 (P Bound n1 ty1)]
397455
398456 -- try to hunt match a typeclass constraint by replacing it with an instance
399− results4 = results4A ++ results4B
400− typeClassArgs classes = [ ((n, ty), inst) | (n, ty) <- classes, inst <- possClassInstances usedNames ty ]
401− results4A = [ State [] [] []
402− (deleteFromArgList n c1 ++ newClassArgs) c2
403− (scoreAcc `mappend` (mempty { leftTypeClassApp = 1 }))
404− (usedNames ++ newHoles)
405− | ((n, ty), inst) <- typeClassArgs c1
406− , newClassArgs <- maybeToList $ typeclassUnify classInfo ctxt ty inst
407− , let newHoles = map fst newClassArgs ]
408− results4B = [ State [] [] []
409− c1 (deleteFromArgList n c2 ++ newClassArgs)
410− (scoreAcc `mappend` (mempty { rightTypeClassApp = 1 }))
411− (usedNames ++ newHoles)
412− | ((n, ty), inst) <- typeClassArgs c2
413− , newClassArgs <- maybeToList $ typeclassUnify classInfo ctxt ty inst
414− , let newHoles = map fst newClassArgs ]
457+ results4 = [ State [] (both (\(cs, _, _) -> ([], cs)) sds)
458+ (scoreAcc `mappend` Score 0 0 (both (\(_, amods, _) -> amods) sds))
459+ (usedns ++ sided (++) (both (\(_, _, hs) -> hs) sds))
460+ | sds <- allMods ]
461+ where
462+ allMods = parallel defMod mods
463+ mods :: Sided [( Classes, AsymMods, [Name] )]
464+ mods = both (instanceMods . snd) unresolved
465+ defMod :: Sided (Classes, AsymMods, [Name])
466+ defMod = both (\(_, cs) -> (cs, mempty , [])) unresolved
467+ parallel :: Sided a -> Sided [a] -> [Sided a]
468+ parallel (Sided l r) (Sided ls rs) = map (flip Sided r) ls ++ map (Sided l) rs
469+ instanceMods :: Classes -> [( Classes , AsymMods, [Name] )]
470+ instanceMods classes = [ ( newClassArgs, mempty { typeClassApp = 1 }, newHoles )
471+ | (_, ty) <- classes
472+ , inst <- possClassInstances usedns ty
473+ , newClassArgs <- maybeToList $ typeclassUnify classInfo ctxt ty inst
474+ , let newHoles = map fst newClassArgs ]
415475
416476
417477 -- Stage 1 - match arguments
418− nextSteps (State holes dag1 dag2 c1 c2 scoreAcc usedNames) = results where
478+ nextSteps (State hs (Sided (dagL, c1) (dagR, c2)) scoreAcc usedns) = results where
419479
420480 results = concatMap takeSomeClasses results1
421481
@@ -425,18 +485,29 @@ matchTypesBulk istate maxScore type1 types = getAllResults startQueueOfQueues wh
425485 canBeFirst = map fst . filter (S.null . snd . snd)
426486
427487 -- try to match an argument from the left with an argument from the right
428− results1 = catMaybes [ unifyQueue (State (filter (not . (`elem` [n1,n2]) . fst) holes) (deleteFromDag n1 dag1)
429− ((inArgTys subst2for1) $ deleteFromDag n2 dag2) c1 (map (second subst2for1) c2) scoreAcc usedNames) [(ty1, ty2)]
430− | (n1, ty1) <- canBeFirst dag1, (n2, ty2) <- canBeFirst dag2, let subst2for1 = psubst n2 (P Bound n1 ty1)]
431−
432−
433− -- Stage 2 - simply introduce a subset of the typeclasses
434− -- we've finished, so take some classes
435− takeSomeClasses (State [] [] [] c1 c2 scoreAcc usedNames) =
436− let lc1 = length c1; lc2 = length c2 in
437− [ State [] [] [] c1' c2' (scoreAcc `mappend`
438− mempty { rightTypeClassIntro = lc1 - length c1',
439− leftTypeClassIntro = lc2 - length c2' }) usedNames
440− | c1' <- subsets c1, c2' <- subsets c2 ]
441− -- still have arguments to match, so just be the identity
442− takeSomeClasses s = [s]
488+ results1 = catMaybes [ unifyQueue (State (filter (not . (`elem` [n1,n2]) . fst) hs)
489+ (Sided (deleteFromDag n1 dagL, c1)
490+ (inArgTys subst2for1 $ deleteFromDag n2 dagR, map (second subst2for1) c2))
491+ scoreAcc usedns) [(ty1, ty2)]
492+ | (n1, ty1) <- canBeFirst dagL, (n2, ty2) <- canBeFirst dagR
493+ , let subst2for1 = psubst n2 (P Bound n1 ty1)]
494+
495+
496+
497+ -- Stage 2 - simply introduce a subset of the typeclasses
498+ -- we've finished, so take some classes
499+ takeSomeClasses (State [] unresolved@(Sided ([], _) ([], _)) scoreAcc usedns) =
500+ map statesFromMods . prod $ both (classMods . snd) unresolved
501+ where
502+ swap (Sided l r) = Sided r l
503+ statesFromMods :: Sided (Classes, AsymMods) -> State
504+ statesFromMods sides = let classes = both (\(c, _) -> ([], c)) sides
505+ mods = swap (both snd sides) in
506+ State [] classes (scoreAcc `mappend` (mempty { asymMods = mods })) usedns
507+ classMods :: Classes -> [(Classes, AsymMods)]
508+ classMods cs = let lcs = length cs in
509+ [ (cs', mempty { typeClassIntro = lcs - length cs' }) | cs' <- subsets cs ]
510+ prod :: Sided [a] -> [Sided a]
511+ prod (Sided ls rs) = [Sided l r | l <- ls, r <- rs]
512+ -- still have arguments to match, so just be the identity
513+ takeSomeClasses s = [s]