What `reify` sees in Template Haskell

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

What `reify` sees in Template Haskell

Francesco Mazzoli
Hi,

I recently stumbled upon the issue of `reify` not being able to give
information about local variables, as of GHC 7.8.  For example, this
won't work:

    foo x = $(do {xInfo <- reify 'x; ...})

The motivation for this change is described here:
<https://ghc.haskell.org/trac/ghc/wiki/TemplateHaskell/BlogPostChanges#PartC:Reificationandtypechecking>.

While I agree that getting the type of local variables is going to be
brittle, I also think that offering that functionality is extremely
useful in certain cases, such as in the case of the language-c-inline
library, that used this facility to avoid having to type verbose type
annotations -- see
<https://github.com/mchakravarty/language-c-inline/issues/25>.

My two part question is:

  1. would it be possible to revert to the old behavior easily, or is
doing that difficult or impossible now given the overall changes to
the Template Haskell code?
  2. if 1, wouldn't it make more sense to allow reifying all names if
the user really wants, maybe with a specific `unsafeReify` function or
similar?

It should be made clear in the docs that by using `unsafeReify` the
user is relying on GHC internals (specifically the internals of type
checking).

Also, I think that post should at least be referenced in the manual,
for lack of better documentation.  This behavior is not mentioned
anywhere else.

Thanks,
Francesco

Reply | Threaded
Open this post in threaded view
|

What `reify` sees in Template Haskell

Simon Peyton Jones
|    1. would it be possible to revert to the old behavior easily, or is
|  doing that difficult or impossible now given the overall changes to
|  the Template Haskell code?

I don?t think it would be difficult to recover the old behaviour, but it's not clear to me that it would be a Good Thing.  A program that works today, and then does not work tomorrow because of some incidental change to the way type inference works, would not be a happy state of affairs.

Perhaps if 'x' had a type annotation that would be ok.  Or maybe there is something else about your intended application that makes it solidly predictable.

By all means start a wiki page to sketch a design for what you think should happen, and why it should be predicable.


Meanwhile, if you would care to draft the bit of user-manual material that you wish had been there, I could review it and put it in.

Thanks!

Simon

|  -----Original Message-----
|  From: Francesco Mazzoli [mailto:f at mazzo.li]
|  Sent: 13 February 2015 12:54
|  To: ghc-devs at haskell.org
|  Cc: Simon Peyton Jones
|  Subject: What `reify` sees in Template Haskell
|  
|  Hi,
|  
|  I recently stumbled upon the issue of `reify` not being able to give
|  information about local variables, as of GHC 7.8.  For example, this
|  won't work:
|  
|      foo x = $(do {xInfo <- reify 'x; ...})
|  
|  The motivation for this change is described here:
|  <https://ghc.haskell.org/trac/ghc/wiki/TemplateHaskell/BlogPostChanges
|  #PartC:Reificationandtypechecking>.
|  
|  While I agree that getting the type of local variables is going to be
|  brittle, I also think that offering that functionality is extremely
|  useful in certain cases, such as in the case of the language-c-inline
|  library, that used this facility to avoid having to type verbose type
|  annotations -- see <https://github.com/mchakravarty/language-c-
|  inline/issues/25>.
|  
|  My two part question is:
|  
|    1. would it be possible to revert to the old behavior easily, or is
|  doing that difficult or impossible now given the overall changes to
|  the Template Haskell code?
|    2. if 1, wouldn't it make more sense to allow reifying all names if
|  the user really wants, maybe with a specific `unsafeReify` function or
|  similar?
|  
|  It should be made clear in the docs that by using `unsafeReify` the
|  user is relying on GHC internals (specifically the internals of type
|  checking).
|  
|  Also, I think that post should at least be referenced in the manual,
|  for lack of better documentation.  This behavior is not mentioned
|  anywhere else.
|  
|  Thanks,
|  Francesco

Reply | Threaded
Open this post in threaded view
|

What `reify` sees in Template Haskell

Francesco Mazzoli
Hi Simon,

On 13 February 2015 at 18:12, Simon Peyton Jones <simonpj at microsoft.com> wrote:
> I don?t think it would be difficult to recover the old behaviour, but it's not clear to me that it would be a Good Thing.  A program that works today, and then does not work tomorrow because of some incidental change to the way type inference works, would not be a happy state of affairs.

In much the same way, programs that rely on the memory representation
that GHC uses for objects can be written with the provided unsafe
functions.  In my view, if you make this danger clear, having those
functions is much better than not having them.  And it seems like the
Haskell environment generally agree with this view.

In any case, if I think of some reasonable but more permissive
restriction, I'll write it up.

> Meanwhile, if you would care to draft the bit of user-manual material that you wish had been there, I could review it and put it in.

I'll try to get some writing done regarding this and the FFI wiki page
next week.

Francesco

Reply | Threaded
Open this post in threaded view
|

What `reify` sees in Template Haskell

Reid Barton-2
On Fri, Feb 13, 2015 at 12:43 PM, Francesco Mazzoli <f at mazzo.li> wrote:

> Hi Simon,
>
> On 13 February 2015 at 18:12, Simon Peyton Jones <simonpj at microsoft.com>
> wrote:
> > I don?t think it would be difficult to recover the old behaviour, but
> it's not clear to me that it would be a Good Thing.  A program that works
> today, and then does not work tomorrow because of some incidental change to
> the way type inference works, would not be a happy state of affairs.
>
> In much the same way, programs that rely on the memory representation
> that GHC uses for objects can be written with the provided unsafe
> functions.  In my view, if you make this danger clear, having those
> functions is much better than not having them.  And it seems like the
> Haskell environment generally agree with this view.
>

Right, but the users of such features understand that their programs may
break under future versions of GHC, and don't expect to have any particular
recourse if this happens.

And this is essentially what happened here. It doesn't make sense to ask
about the type of a variable in a TH splice when the result of that splice
might affect what type the variable has! Admittedly it was not documented
that the behavior of reify was undefined in this case, but I imagine that's
because nobody had considered this scenario (if they had, we'd have had the
7.8 design from the start).

I don't like it more than anyone else when GHC breaks user programs, but
when those programs were dependent on undefined behavior, I think it's
incumbent on the user to find a way to rewrite their program so as to not
depend on undefined behavior. This might include requesting a new GHC
feature with well-defined semantics. Adding the old undefined behavior
should be a last resort, and then in the future the undefined behavior
might stop giving you the answer you want anyways.


> In any case, if I think of some reasonable but more permissive
> restriction, I'll write it up.
>

Have you tried using Typed TH splices? Those interact differently with the
type checker, because the type of the expression resulting from a splice is
determined by the type of the splice action, and cannot depend upon its
value. So, it seems to me that it would be fine to allow reify to ask about
the type of a local variable from within a typed splice, and it may work
that way already (I haven't tried it).

Regards,
Reid Barton
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://www.haskell.org/pipermail/ghc-devs/attachments/20150213/9a127f05/attachment.html>