How to extract name and type of exported functions in modules

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
6 messages Options
Reply | Threaded
Open this post in threaded view
|

How to extract name and type of exported functions in modules

Oscar Finnsson
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
[hidden email]
http://www.haskell.org/mailman/listinfo/template-haskell
Reply | Threaded
Open this post in threaded view
|

The template-haskell@haskell.org mailing list

Simon Peyton Jones
Question: is the [hidden email] 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
_______________________________________________
template-haskell mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/template-haskell
Reply | Threaded
Open this post in threaded view
|

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

Simon Peyton Jones
In reply to this post by Oscar Finnsson
[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: [hidden email] [mailto:template-haskell-
| [hidden email]] On Behalf Of Oscar Finnsson
| Sent: 16 October 2009 18:47
| To: [hidden email]
| 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
| [hidden email]
| http://www.haskell.org/mailman/listinfo/template-haskell

_______________________________________________
template-haskell mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/template-haskell
Reply | Threaded
Open this post in threaded view
|

Re: The template-haskell@haskell.org mailing list

Sean Leather
In reply to this post by Simon Peyton Jones

On Tue, Oct 20, 2009 at 16:37, Simon Peyton-Jones wrote:
Question: is the [hidden email] 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

_______________________________________________
template-haskell mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/template-haskell
Reply | Threaded
Open this post in threaded view
|

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

Simon Peyton Jones
In reply to this post by Simon Peyton Jones
| -- 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
_______________________________________________
template-haskell mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/template-haskell
Reply | Threaded
Open this post in threaded view
|

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

Oscar Finnsson
In reply to this post by Simon Peyton Jones
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
<[hidden email]> 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: [hidden email] [mailto:template-haskell-
> | [hidden email]] On Behalf Of Oscar Finnsson
> | Sent: 16 October 2009 18:47
> | To: [hidden email]
> | 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
> | [hidden email]
> | http://www.haskell.org/mailman/listinfo/template-haskell
>
>
_______________________________________________
template-haskell mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/template-haskell