Oscar Finnsson | 16 Oct 2009 19:47
Picon
Gravatar

How to extract name and type of exported functions in modules

Hi,

I'm trying to extract the names and types of exported functions in a module.

At the moment I've managed to get a list of all functions in a module
but I can't seem to figure out how to get their types.

Lets say I got the module

    module Foo where

    foo1 :: String -> String
    foo1 value = value

    foo2 = "hej"

and then in anothor module...

    module Bar where

    bar = $(getAllFunctions "<some-path>/Foo.hs")

At the moment I got getAllFunctions returning ["foo1","foo2"], but I
would really like to get it to return [("foo1",AppT (ConT "String")
(ConT "String")), ("foo2",ConT "String")]

Using "parseModuleWithMode" from Language.Haskell.Exts I can get hold
of the names and the type signature of foo1 (since it's specified in
the source code) but I cannot get hold of the type signature of foo2
(since it's not specified in the source code).
(Continue reading)

Simon Peyton-Jones | 20 Oct 2009 16:37
Picon
Favicon
Gravatar

The template-haskell <at> haskell.org mailing list

Question: is the template-haskell <at> haskell.org mailing list still useful?  

  * It has 250 subscribers compared to 850 for ghc-users.  
  * It has low traffic
  * template-haskell is the only GHC-specific mailing list associated with a particular
    language feature.  Eg type functions, ghci, etc do not have their own list
  * The traffic on ghc-users is not dauntingly high.

I suggest we abolish it in favour of ghc-users.  Any dissenters?  (I'd emit a warning, so that people could
check they are subscribed to ghc-users.)

Simon
Sean Leather | 20 Oct 2009 17:03
Picon

Re: [Template-haskell] The template-haskell <at> haskell.org mailing list


On Tue, Oct 20, 2009 at 16:37, Simon Peyton-Jones wrote:
Question: is the template-haskell <at> haskell.org mailing list still useful?

My gut reaction: probably not.
 
 * It has 250 subscribers compared to 850 for ghc-users.
 * It has low traffic
 * template-haskell is the only GHC-specific mailing list associated with a particular
   language feature.  Eg type functions, ghci, etc do not have their own list
 * The traffic on ghc-users is not dauntingly high.

Also telling is the fact that so many threads are begun and left to rot (i.e. questions remain unanswered). My impression is that very few people actually pay attention to the template-haskell list.

I suggest we abolish it in favour of ghc-users.  Any dissenters?  (I'd emit a warning, so that people could check they are subscribed to ghc-users.)

Not here.

Sean
_______________________________________________
Glasgow-haskell-users mailing list
Glasgow-haskell-users <at> haskell.org
http://www.haskell.org/mailman/listinfo/glasgow-haskell-users
Günther Schmidt | 20 Oct 2009 18:24

Re: The template-haskell <at> haskell.org mailing list

Hi,

would that move preserve the archive?

Günther

Am 20.10.2009, 16:37 Uhr, schrieb Simon Peyton-Jones  
<simonpj <at> microsoft.com>:

> Question: is the template-haskell <at> haskell.org mailing list still useful?
>
>   * It has 250 subscribers compared to 850 for ghc-users.
>   * It has low traffic
>   * template-haskell is the only GHC-specific mailing list associated  
> with a particular
>     language feature.  Eg type functions, ghci, etc do not have their  
> own list
>   * The traffic on ghc-users is not dauntingly high.
>
> I suggest we abolish it in favour of ghc-users.  Any dissenters?  (I'd  
> emit a warning, so that people could check they are subscribed to  
> ghc-users.)
>
> Simon
> _______________________________________________
> Glasgow-haskell-users mailing list
> Glasgow-haskell-users <at> haskell.org
> http://www.haskell.org/mailman/listinfo/glasgow-haskell-users
Simon Marlow | 21 Oct 2009 14:08
Picon

Re: The template-haskell <at> haskell.org mailing list

On 20/10/2009 17:24, Günther Schmidt wrote:
> Hi,
>
> would that move preserve the archive?

It's possible to remove the mailing list facility itself without 
removing the archive, I believe.  I'm not sure whether it leaves the web 
page for the mailing list in place, and if not, how the archives could 
be found.

Cheers,
	Simon
Simon Peyton-Jones | 20 Oct 2009 16:38
Picon
Favicon
Gravatar

RE: How to extract name and type of exported functions in modules

[ccing ghc-users]

| I'm trying to extract the names and types of exported functions in a module.

Quite a reasonable request.  But it's not conveniently possible at the moment.  Here's what you can do in the Q monad:

class (Monad m, Functor m) => Quasi m where
	-- Fresh names
  qNewName :: String -> m Name

	-- Error reporting and recovery
  qReport  :: Bool -> String -> m ()	-- Report an error (True) or warning (False)
					-- ...but carry on; use 'fail' to stop
  qRecover :: m a -> m a -> m a		-- Recover from the monadic 'fail'
					-- The first arg is the error handler

	-- Inspect the type-checker's environment
  qReify :: Name -> m Info
  qLocation :: m Loc

	-- Input/output (dangerous)
  qRunIO :: IO a -> m a

But you want one more function:

  qReifyModule :: String -> m ModuleInfo

where ModuleInfo is something like:

data ModuleInfo = MI { mi_exports :: [Name]
                     , ... instances,rules, etc }

Then you could use qReify to get info about a particular thing.

This would not be hard in principle, the details need thought.  For example, if module exports T( C1, C2),
where C1, C2 are constructors of T which also has constructors C3, C4, what should appear in mi_exports? 
Should mi_exports reflect the structure of the export list (see the AvailInfo type in GHC).

What is the info for an instance?
Do we need a way to ask for all the instances of a class (or rules for a function) regardless of what module
those instances come from?   etc

Does this ring bells for anyone else?  Would someone like to write the spec?  Are there other reify-related
things that we need?

Simon

| -----Original Message-----
| From: template-haskell-bounces <at> haskell.org [mailto:template-haskell-
| bounces <at> haskell.org] On Behalf Of Oscar Finnsson
| Sent: 16 October 2009 18:47
| To: template-haskell <at> haskell.org
| Subject: [Template-haskell] How to extract name and type of exported functions in
| modules
| 
| Hi,
| 
| I'm trying to extract the names and types of exported functions in a module.
| 
| At the moment I've managed to get a list of all functions in a module
| but I can't seem to figure out how to get their types.
| 
| Lets say I got the module
| 
|     module Foo where
| 
|     foo1 :: String -> String
|     foo1 value = value
| 
|     foo2 = "hej"
| 
| and then in anothor module...
| 
|     module Bar where
| 
|     bar = $(getAllFunctions "<some-path>/Foo.hs")
| 
| At the moment I got getAllFunctions returning ["foo1","foo2"], but I
| would really like to get it to return [("foo1",AppT (ConT "String")
| (ConT "String")), ("foo2",ConT "String")]
| 
| Using "parseModuleWithMode" from Language.Haskell.Exts I can get hold
| of the names and the type signature of foo1 (since it's specified in
| the source code) but I cannot get hold of the type signature of foo2
| (since it's not specified in the source code).
| 
| Is there another way to get the names/signatures of exported functions
| from a module other than using parseModuleWithMode so the developer
| writing the Foo-module isn't forced to explicitly supply type
| signatures of the exported functions?
| 
| If I try "reify" to get information about the functions I get the error message:
| "foo1 is not in scope at a reify"
| 
| This seems to be a known bug about reify (reported here
| http://hackage.haskell.org/trac/ghc/ticket/2339). My problem is that I
| cannot use the workaround since I don't know the name of the
| functions.
| 
| Another disadvantage with this approach is that "getAllFunctions" must
| have access to the source code of the module and that I must supply
| the path the the module. If possible I would like to have code such as
| 
|     bar = $(getAllFunctions "Foo")
| 
| instead of "<come-path>/Foo.hs".
| 
| Regards,
| Oscar Finnsson
| _______________________________________________
| template-haskell mailing list
| template-haskell <at> haskell.org
| http://www.haskell.org/mailman/listinfo/template-haskell
kahl | 20 Oct 2009 20:20
Picon
Picon
Favicon

Re: [Template-haskell] How to extract name and type of exported functions in modules

Simon Peyton Jones wrote:

 > What is the info for an instance?
 > Do we need a way to ask for all the instances of a class
 > (or rules for a function)
 > regardless of what module those instances come from?   etc
 > 
 > 
 > Does this ring bells for anyone else?

It does --- but completely outside the context of Template-Haskell.

I have been trying to do things via the GHC API (the full API,
not just module GHC), and found it surprisingly hard to obtain
all exports for a given module
(whether source or compiled library module):

-- If it exports any prelude indentifiers (not only the Prelude itself,
   but also for example Data.List), I have no idea how to get at
   their types --- lookupGlobalName does not find them.

-- I cannot find any re-exported instances. The ``package InstEnv''
   obtained from tcGetInstEnvs after loading a library module interface
   (via findAndReadIface) seems to contain only the module's own exported
   instances, which are the same instances I also find via mi_insts.
   (For source modules, where I use typeCheckModule,
    I've only been able to find the module's own exported instances via
    hptInstances).

   Even while not counting the missing Prelude instances,
   Data.Map is still re-exporting the Data.Set instances from the same
   package --- where does GHC keep those?
   And where does it keep those from different packages?
   my current understanding of the ``home InstEnv'' is that it contains
   instances encountered during ``ghc --make'' that may not be visible in
   the current module, so if I ever do find instances there,
   how would I filter the visible ones?

 > Do we need a way to ask for all the instances of a class
 > (or rules for a function)
 > regardless of what module those instances come from?   etc

As long as a module re-exports an instance, I'd like to be able to find it
from that module.

 > For example, if module exports T( C1, C2), where C1, C2 are constructors
 > of T which also has constructors C3, C4, what should appear in
 > mi_exports?  Should mi_exports reflect the structure of the export list
 > (see the AvailInfo type in GHC).

Applications that look at a module ``from the outside''
should, in my opinion, not be able see C3 and C4.
I think they also do not need to be able to know
that there are additional constructors.
There is always _|_ that doesn't match C1 nor C2,
even if there are no C3 nor C4.

Applications that need to know more will want an interface
that allows to ``look at all the insides'' of a module,
i.e., they want access to all items defined and imported inside,
and may of course also want to know which of these items are exported.

Since there are other interfaces to find out that C1 and C2 belong to T,
I don't think it is essential to know the structure of the export list.
It may be convenient, though...

(By the way, IIRC, sometimes I can import C1 as ``C1'',
 and sometimes I need to import it as ``T(C1)''.
 Is this a side effect of some LANGUAGE extension?)

Wolfram
Simon Peyton-Jones | 21 Oct 2009 13:40
Picon
Favicon
Gravatar

RE: [Template-haskell] How to extract name and type of exported functions in modules

| -- If it exports any prelude indentifiers (not only the Prelude itself,
|    but also for example Data.List), I have no idea how to get at
|    their types --- lookupGlobalName does not find them.

Well, it claims that it should find them.   Would you like to make a reproducible test case and file a Trac bug report?

| -- I cannot find any re-exported instances. The ``package InstEnv''
|    obtained from tcGetInstEnvs after loading a library module interface
|    (via findAndReadIface) seems to contain only the module's own exported
|    instances, which are the same instances I also find via mi_insts.
|    (For source modules, where I use typeCheckModule,
|     I've only been able to find the module's own exported instances via
|     hptInstances).

Hmm.  GHC does not read every interface file for every module in every package that is transitively visible
from the current module.  Instead it relies on the fact that before an instance (C T) is useful, you must have
a hold of Class C and TyCon T.  So you'll have loaded *their* interfaces, and thereby loaded their
instances. (Except for orphan instances, which *are* loaded eagerly.)

I can see that this is inconvenient; on the other hand, do you really want ALL the instances of Ord, say?  

Perhaps there should be an interface for
	load instances that relate to the following Names
Indeed, there is: LoadIface.loadInterfaceForName.

Does that help?  What's the desired behaviour?

I really wish there was someone who took ownership for the GHC API, as seen by "customers" of the API.  At the
moment it grows incrementally, without proper design.  Maybe no one feels able to, because they think GHC
HQ will do it, but (a) we are too busy and (b) we represent the suppliers of the API, not the customers.

Any volunteeers?

Simon
Oscar Finnsson | 29 Oct 2009 22:26
Picon
Gravatar

Re: How to extract name and type of exported functions in modules

Thanks for the pointers. Using the GHC API I've managed to extract the
names and types of exported functions from other packages (haven't
managed to figure out how to extract from the modules in the current
package but I'm working on it). I'll post the source code of my
"reifyModule" on github once it is cleaned up.

First I thought I would examine the source code of template-haskell
(more specifically qLocation and qReify) to figure out how to do it
but got stuck. Obviously I have still much to learn when it comes to
Haskell.

Could someone explain how Quasi works?

I see:

instance Quasi Q where
  qReify    = reify
  qLocation = location
  ...

instance Quasi IO where
  qLocation = badIO "currentLocation"
  qReity = badIO "reify"
  ...

location :: Q Loc
location = Q qLocation

I guess this means that a Q will ask the embedded Quasi for the
location until the Quasi either returns badIO "currentLocation" or
...?
The only way this can work (as fast as I can see) is if where is
another instance of Quasi than Q and IO but I cannot find that
instance in the source code.

-- Oscar

On Tue, Oct 20, 2009 at 4:38 PM, Simon Peyton-Jones
<simonpj <at> microsoft.com> wrote:
> [ccing ghc-users]
>
> | I'm trying to extract the names and types of exported functions in a module.
>
> Quite a reasonable request.  But it's not conveniently possible at the moment.  Here's what you can do
in the Q monad:
>
> class (Monad m, Functor m) => Quasi m where
>        -- Fresh names
>  qNewName :: String -> m Name
>
>        -- Error reporting and recovery
>  qReport  :: Bool -> String -> m ()    -- Report an error (True) or warning (False)
>                                        -- ...but carry on; use 'fail' to stop
>  qRecover :: m a -> m a -> m a         -- Recover from the monadic 'fail'
>                                        -- The first arg is the error handler
>
>        -- Inspect the type-checker's environment
>  qReify :: Name -> m Info
>  qLocation :: m Loc
>
>        -- Input/output (dangerous)
>  qRunIO :: IO a -> m a
>
> But you want one more function:
>
>  qReifyModule :: String -> m ModuleInfo
>
> where ModuleInfo is something like:
>
> data ModuleInfo = MI { mi_exports :: [Name]
>                     , ... instances,rules, etc }
>
> Then you could use qReify to get info about a particular thing.
>
>
> This would not be hard in principle, the details need thought.  For example, if module exports T( C1, C2),
where C1, C2 are constructors of T which also has constructors C3, C4, what should appear in mi_exports?
 Should mi_exports reflect the structure of the export list (see the AvailInfo type in GHC).
>
> What is the info for an instance?
> Do we need a way to ask for all the instances of a class (or rules for a function) regardless of what module
those instances come from?   etc
>
>
> Does this ring bells for anyone else?  Would someone like to write the spec?  Are there other
reify-related things that we need?
>
> Simon
>
> | -----Original Message-----
> | From: template-haskell-bounces <at> haskell.org [mailto:template-haskell-
> | bounces <at> haskell.org] On Behalf Of Oscar Finnsson
> | Sent: 16 October 2009 18:47
> | To: template-haskell <at> haskell.org
> | Subject: [Template-haskell] How to extract name and type of exported functions in
> | modules
> |
> | Hi,
> |
> | I'm trying to extract the names and types of exported functions in a module.
> |
> | At the moment I've managed to get a list of all functions in a module
> | but I can't seem to figure out how to get their types.
> |
> | Lets say I got the module
> |
> |     module Foo where
> |
> |     foo1 :: String -> String
> |     foo1 value = value
> |
> |     foo2 = "hej"
> |
> | and then in anothor module...
> |
> |     module Bar where
> |
> |     bar = $(getAllFunctions "<some-path>/Foo.hs")
> |
> | At the moment I got getAllFunctions returning ["foo1","foo2"], but I
> | would really like to get it to return [("foo1",AppT (ConT "String")
> | (ConT "String")), ("foo2",ConT "String")]
> |
> | Using "parseModuleWithMode" from Language.Haskell.Exts I can get hold
> | of the names and the type signature of foo1 (since it's specified in
> | the source code) but I cannot get hold of the type signature of foo2
> | (since it's not specified in the source code).
> |
> | Is there another way to get the names/signatures of exported functions
> | from a module other than using parseModuleWithMode so the developer
> | writing the Foo-module isn't forced to explicitly supply type
> | signatures of the exported functions?
> |
> | If I try "reify" to get information about the functions I get the error message:
> | "foo1 is not in scope at a reify"
> |
> | This seems to be a known bug about reify (reported here
> | http://hackage.haskell.org/trac/ghc/ticket/2339). My problem is that I
> | cannot use the workaround since I don't know the name of the
> | functions.
> |
> | Another disadvantage with this approach is that "getAllFunctions" must
> | have access to the source code of the module and that I must supply
> | the path the the module. If possible I would like to have code such as
> |
> |     bar = $(getAllFunctions "Foo")
> |
> | instead of "<come-path>/Foo.hs".
> |
> | Regards,
> | Oscar Finnsson
> | _______________________________________________
> | template-haskell mailing list
> | template-haskell <at> haskell.org
> | http://www.haskell.org/mailman/listinfo/template-haskell
>
>
Simon Peyton-Jones | 30 Oct 2009 11:16
Picon
Favicon
Gravatar

RE: [Template-haskell] How to extract name and type of exported functions in modules

| First I thought I would examine the source code of template-haskell
| (more specifically qLocation and qReify) to figure out how to do it
| but got stuck. Obviously I have still much to learn when it comes to
| Haskell.
| 
| Could someone explain how Quasi works?

Have you read the paper?  Referred to from here
http://www.haskell.org/ghc/docs/latest/html/users_guide/template-haskell.html, the
particular bit you want is Section 10 of http://research.microsoft.com/~simonpj/papers/meta-haskell/notes2.ps

| The only way this can work (as fast as I can see) is if where is
| another instance of Quasi than Q and IO but I cannot find that
| instance in the source code.

Yes indeed there is -- the type checker monad!  See TcSplice line 819.

Simon

Gmane