From 5affd8114e7ba87fa289eb72760a597456aea4cb Mon Sep 17 00:00:00 2001 From: simonpj Date: Thu, 3 Jul 2003 14:33:22 +0000 Subject: [PATCH] [project @ 2003-07-03 14:33:18 by simonpj] ----------------------- Type defaulting in GHCi ----------------------- [Merge to stable branch, I think.] Extend type defaulting in GHCi so that ghci> [] [] works. Suggested by Ralf Hinze. --- ghc/compiler/rename/RnEnv.lhs | 10 ++++- ghc/compiler/typecheck/TcSimplify.lhs | 75 +++++++++++++++++++-------------- ghc/docs/users_guide/ghci.sgml | 26 ++++++++++++ 3 files changed, 77 insertions(+), 34 deletions(-) diff --git a/ghc/compiler/rename/RnEnv.lhs b/ghc/compiler/rename/RnEnv.lhs index 68b09c6..e08a8c0 100644 --- a/ghc/compiler/rename/RnEnv.lhs +++ b/ghc/compiler/rename/RnEnv.lhs @@ -39,7 +39,7 @@ import Module ( Module, ModuleName, moduleName, mkHomeModule, import PrelNames ( mkUnboundName, intTyConName, boolTyConName, funTyConName, unpackCStringName, unpackCStringFoldrName, unpackCStringUtf8Name, - eqStringName, printName, + eqStringName, printName, integerTyConName, bindIOName, returnIOName, failIOName, thenIOName ) #ifdef GHCI @@ -564,9 +564,15 @@ mentioned explicitly, but which might be needed by the type checker. implicitStmtFVs source_fvs -- Compiling a statement = stmt_fvs `plusFV` implicitModuleFVs source_fvs where - stmt_fvs = mkFVs [printName, bindIOName, thenIOName, returnIOName, failIOName] + stmt_fvs = mkFVs [printName, bindIOName, thenIOName, returnIOName, failIOName, + integerTyConName] -- These are all needed implicitly when compiling a statement -- See TcModule.tc_stmts + -- Reason for integerTyConName: consider this in GHCi + -- ghci> [] + -- We get an ambigous constraint (Show a), which we now default just like + -- numeric types... but unless we have the instance decl for Integer we + -- won't find a valid default! implicitModuleFVs source_fvs = mkTemplateHaskellFVs source_fvs `plusFV` diff --git a/ghc/compiler/typecheck/TcSimplify.lhs b/ghc/compiler/typecheck/TcSimplify.lhs index 999d390..31f3255 100644 --- a/ghc/compiler/typecheck/TcSimplify.lhs +++ b/ghc/compiler/typecheck/TcSimplify.lhs @@ -53,7 +53,8 @@ import NameSet ( NameSet, mkNameSet, elemNameSet ) import Class ( classBigSig ) import FunDeps ( oclose, grow, improve, pprEquationDoc ) import PrelInfo ( isNumericClass, isCreturnableClass, isCcallishClass ) -import PrelNames ( splitName, fstName, sndName ) +import PrelNames ( splitName, fstName, sndName, showClassKey ) +import HscTypes ( GhciMode(Interactive) ) import Subst ( mkTopTyVarSubst, substTheta, substTy ) import TysWiredIn ( unitTy, pairTyCon ) @@ -63,6 +64,7 @@ import VarEnv ( TidyEnv ) import FiniteMap import Outputable import ListSetOps ( equivClasses ) +import Unique ( hasKey ) import Util ( zipEqual, isSingleton ) import List ( partition ) import CmdLineOpts @@ -1646,8 +1648,12 @@ tcSimplifyTop wanteds (tidy_env, tidy_dicts) = tidyInsts bad_guys (bad_ips, non_ips) = partition isIPDict tidy_dicts (no_insts, ambigs) = partition no_inst non_ips - no_inst d = not (isTyVarDict d) || tyVarsOfInst d `subVarSet` fixed_tvs - fixed_tvs = oclose (fdPredsOfInsts tidy_dicts) emptyVarSet + no_inst d = not (isTyVarDict d) + -- Previously, there was a more elaborate no_inst definition: + -- no_inst d = not (isTyVarDict d) || tyVarsOfInst d `subVarSet` fixed_tvs + -- fixed_tvs = oclose (fdPredsOfInsts tidy_dicts) emptyVarSet + -- But that seems over-elaborate to me; it only bites for class decls with + -- fundeps like this: class C a b | -> b where ... in -- Report definite errors @@ -1668,7 +1674,8 @@ tcSimplifyTop wanteds addTopAmbigErrs (tidy_env, ambigs) `thenM_` -- Disambiguate the ones that look feasible - mappM disambigGroup std_oks + getGhciMode `thenM` \ mode -> + mappM (disambigGroup mode) std_oks ) `thenM` \ binds_ambig -> returnM (binds `andMonoBinds` andMonoBindList binds_ambig) @@ -1715,12 +1722,13 @@ Since we're not using the result of @foo@, the result if (presumably) @void@. \begin{code} -disambigGroup :: [Inst] -- All standard classes of form (C a) +disambigGroup :: GhciMode + -> [Inst] -- All standard classes of form (C a) -> TcM TcDictBinds -disambigGroup dicts - | any isNumericClass classes -- Guaranteed all standard classes - -- see comment at the end of function for reasons as to +disambigGroup ghci_mode dicts + | any std_default_class classes -- Guaranteed all standard classes + -- See comment at the end of function for reasons as to -- why the defaulting mechanism doesn't apply to groups that -- include CCallable or CReturnable dicts. && not (any isCcallishClass classes) @@ -1746,35 +1754,38 @@ disambigGroup dicts in -- See if any default works tryM (try_default default_tys) `thenM` \ mb_ty -> - case mb_ty of { - Left _ -> -- If not, add an AmbigErr - addTopAmbigErrs (tidyInsts dicts) `thenM_` - returnM EmptyMonoBinds ; + case mb_ty of + Left _ -> bomb_out + Right chosen_default_ty -> choose_default chosen_default_ty - Right chosen_default_ty -> + | all isCreturnableClass classes -- Default CCall stuff to () + = choose_default unitTy - -- If so, bind the type variable + | otherwise -- No defaults + = bomb_out + + where + tyvar = get_tv (head dicts) -- Should be non-empty + classes = map get_clas dicts + + std_default_class cls + = isNumericClass cls + || (ghci_mode == Interactive && cls `hasKey` showClassKey) + -- In interactive mode, we default Show a to Show () + -- to avoid graututious errors on "show []" + + choose_default default_ty -- Commit to tyvar = default_ty + = -- Bind the type variable + unifyTauTy default_ty (mkTyVarTy tyvar) `thenM_` -- and reduce the context, for real this time - unifyTauTy chosen_default_ty (mkTyVarTy tyvar) `thenM_` - simpleReduceLoop (text "disambig" <+> ppr dicts) + simpleReduceLoop (text "disambig" <+> ppr dicts) reduceMe dicts `thenM` \ (frees, binds, ambigs) -> - WARN( not (null frees && null ambigs), ppr frees $$ ppr ambigs ) - warnDefault dicts chosen_default_ty `thenM_` - returnM binds } - - | all isCreturnableClass classes - = -- Default CCall stuff to (); we don't even both to check that () is an - -- instance of CReturnable, because we know it is. - unifyTauTy (mkTyVarTy tyvar) unitTy `thenM_` - returnM EmptyMonoBinds + WARN( not (null frees && null ambigs), ppr frees $$ ppr ambigs ) + warnDefault dicts default_ty `thenM_` + returnM binds - | otherwise -- No defaults - = addTopAmbigErrs (tidyInsts dicts) `thenM_` - returnM EmptyMonoBinds - - where - tyvar = get_tv (head dicts) -- Should be non-empty - classes = map get_clas dicts + bomb_out = addTopAmbigErrs (tidyInsts dicts) `thenM_` + returnM EmptyMonoBinds \end{code} [Aside - why the defaulting mechanism is turned off when diff --git a/ghc/docs/users_guide/ghci.sgml b/ghc/docs/users_guide/ghci.sgml index f7a6e06..dfcb955 100644 --- a/ghc/docs/users_guide/ghci.sgml +++ b/ghc/docs/users_guide/ghci.sgml @@ -637,6 +637,32 @@ Wed Mar 14 12:23:13 GMT 2001 of it is lost. + + + Type defaulting in GHCi + Type default + Show class + + Consider this GHCi session: + + ghci> reverse [] + + What should GHCi do? Strictly speaking, the program is ambiguous. show (reverse []) + (which is what GHCi computes here) has type Show a => a and how that displays depends + on the type a. For example: + + ghci> (reverse []) :: String + "" + ghci> (reverse []) :: [Int] + [] + + However, it is tiresome for the user to have to specify the type, so GHCi extends Haskell's type-defaulting + rules (Section 4.3.4 of the Haskell 98 Report (Revised)) as follows. If the expression yields a set of + type constraints that are all from standard classes (Num, Eq etc.), + and at least one is either a numeric class or the Show class, + GHCi will try to use one of the default types, just as described in the Report. + + -- 1.7.10.4