Why do Names defined in the current module lack a module name?

Simon Peyton-Jones simonpj at microsoft.com
Sat Apr 6 01:04:25 CEST 2013


Aha.  You should be looking in the abs_exports field of AbsBinds, not in abs_binds.

I've added some (long-needed) comments to HsBinds, which I append below.

I hope that helps.

Simon

Note [AbsBinds]
~~~~~~~~~~~~~~~
The AbsBinds constructor is used in the output of the type checker, to record
*typechecked* and *generalised* bindings.  Consider a module M, with this
top-level binding
    M.reverse []     = []
    M.reverse (x:xs) = M.reverse xs ++ [x]

In Hindley-Milner, a recursive binding is typechecked with the *recursive* uses
being *monomorphic*.  So after typechecking *and* deugaring we will get something
like this
 
    M.reverse :: forall a. [a] -> [a]
      = /\a. letrec 
                reverse :: [a] -> [a] = \xs -> case xs of
                                                []     -> []
                                                (x:xs) -> reverse xs ++ [x]
             in reverse

Notice that 'M.reverse' is polymorphic as expected, but there is a local
defintion for plain 'reverse' which is *monomorphic*.  The type variable
'a' scopes over the entire letrec.

That's after desugaring.  What about after type checking but before desugaring?  
That's where AbsBinds comes in.  It looks like this:

   AbsBinds { abs_tvs     = [a]
            , abs_exports = [ABE { abe_poly = M.reverse :: forall a. [a] -> [a],
                                 , abe_mono = reverse :: a -> a}]
            , abs_binds = { reverse :: [a] -> [a] 
                               = \xs -> case xs of
                                            []     -> []
                                            (x:xs) -> reverse xs ++ [x] } }

Here,
  * abs_tvs says what type variables are abstracted over the binding group, 
    just 'a' in this case.
  * abs_binds is the *monomorphic* bindings of the group
  * abs_exports describes how to get the polymorphic Id 'M.reverse' from the 
    monomorphic one 'reverse'

Notice that the *original* function (the polymorphic one you thought
you were defining) appears in the abe_poly field of the
abs_exports. The bindings in abs_binds are for fresh, local, Ids with
a *monomorphic* Id.

If there is a group of mutually recusive functions without type
signatures, we get one AbsBinds with the monomorphic versions of the
bindings in abs_binds, and one element of abe_exports for each
variable bound in the mutually recursive group.  This is true even for
pattern bindings.  Example:
        (f,g) = (\x -> x, f)
After type checking we get
   AbsBinds { abs_tvs     = [a]
            , abs_exports = [ ABE { abe_poly = M.f :: forall a. a -> a
                                  , abe_mono = f :: a -> a }
                            , ABE { abe_poly = M.g :: forall a. a -> a
                                  , abe_mono = g :: a -> a }]
            , abs_binds = { (f,g) = (\x -> x, f) }



|  -----Original Message-----
|  From: Johan Tibell [mailto:johan.tibell at gmail.com]
|  Sent: 05 April 2013 18:58
|  To: Simon Peyton-Jones
|  Cc: Manuel M T Chakravarty; ghc-devs at haskell.org
|  Subject: Re: Why do Names defined in the current module lack a module name?
|  
|  Simon,
|  
|  I've created a small standalone test case here:
|  https://gist.github.com/tibbe/5321268
|  
|  Usage:
|  
|  Download the Main.hs and Test.hs files into the same directory:
|  
|  https://gist.github.com/tibbe/5321268/raw/68537a79865209d7218429b916a7ab
|  1ccebc18e4/Main.hs
|  https://gist.github.com/tibbe/5321268/raw/f9cce61b35b3349eeeac622a4c27c1dd
|  5e0410cf/Test.hs
|  
|  Compile and run:
|  ghc Main.hs
|  ./Main
|  
|  Expected output:
|  Loading Test.hs ...
|  ["Test.mysum","Data.List.foldl'","GHC.Num.+"]
|  
|  Actual output:
|  Loading Test.hs ...
|  [".mysum","Data.List.foldl'","GHC.Num.+"]
|  
|  Note how the locally defined and exported function mysum lacks a
|  module name. The code that creates a string from the Name is on line
|  59 in Main.hs:
|  
|      nameToString name = (maybe "" (moduleNameString . moduleName) .
|  nameModule_maybe $ name)
|                          ++ "." ++ getOccString name
|  
|  The module name is missing in the output because nameModule_maybe
|  returns Nothing for the mysum Name.
|  
|  -- Johan



More information about the ghc-devs mailing list