[project @ 2003-07-03 14:33:18 by simonpj]
authorsimonpj <unknown>
Thu, 3 Jul 2003 14:33:22 +0000 (14:33 +0000)
committersimonpj <unknown>
Thu, 3 Jul 2003 14:33:22 +0000 (14:33 +0000)
-----------------------
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
ghc/compiler/typecheck/TcSimplify.lhs
ghc/docs/users_guide/ghci.sgml

index 68b09c6..e08a8c0 100644 (file)
@@ -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` 
index 999d390..31f3255 100644 (file)
@@ -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
index f7a6e06..dfcb955 100644 (file)
@@ -637,6 +637,32 @@ Wed Mar 14 12:23:13 GMT 2001
       of <literal>it</literal> is lost.</para>
 
     </sect2>
+
+    <sect2>
+      <title>Type defaulting in GHCi</title>
+    <indexterm><primary>Type default</primary></indexterm>
+    <indexterm><primary><literal>Show</literal> class</primary></indexterm>
+      <para>
+      Consider this GHCi session:
+<programlisting>
+  ghci> reverse []
+</programlisting>
+      What should GHCi do?  Strictly speaking, the program is ambiguous.  <literal>show (reverse [])</literal>
+      (which is what GHCi computes here) has type <literal>Show a => a</literal> and how that displays depends 
+      on the type <literal>a</literal>.  For example:
+<programlisting>
+  ghci> (reverse []) :: String
+  ""
+  ghci> (reverse []) :: [Int]
+  []
+</programlisting>
+    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 (<literal>Num</literal>, <literal>Eq</literal> etc.), 
+   and at least one is either a numeric class <emphasis>or the <literal>Show</literal> class</emphasis>,
+   GHCi will try to use one of the <literal>default</literal> types, just as described in the Report.
+   </para>
+    </sect2>
   </sect1>
 
   <sect1 id="ghci-invokation">