Proposal: liftData for Template Haskell

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

Proposal: liftData for Template Haskell

Edward Z. Yang
I propose adding the following function to Language.Haskell.TH:

    -- | 'liftData' is a variant of 'lift' in the 'Lift' type class which
    -- works for any type with a 'Data' instance.
    liftData :: Data a => a -> Q Exp
    liftData = dataToExpQ (const Nothing)

I don't really know which submodule this should come from;
since it uses 'dataToExpQ', you might put it in Language.Haskell.TH.Quote
but arguably 'dataToExpQ' doesn't belong in this module either,
and it only lives there because it is a useful function for defining
quasiquoters and it was described in the quasiquoting paper.

I might propose getting rid of the 'Lift' class entirely, but you
might prefer that class since it doesn't go through SYB (and have
the attendant slowdown).

This mode of use of 'dataToExpQ' deserves more attention.

Discussion period: 1 month

Cheers,
Edward
_______________________________________________
Libraries mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
Reply | Threaded
Open this post in threaded view
|

Re: Proposal: liftData for Template Haskell

Richard Eisenberg-2
+1

But don't remove Lift. I need it to be able to lift types that have unlifted(*) data.

(*): Of course, the "lift" root of the word unlifted is entirely unrelated to the use of "lift" earlier in the same sentence. Urgh.

Good idea!
Richard

On Apr 17, 2015, at 7:21 AM, "Edward Z. Yang" <[hidden email]> wrote:

> I propose adding the following function to Language.Haskell.TH:
>
>    -- | 'liftData' is a variant of 'lift' in the 'Lift' type class which
>    -- works for any type with a 'Data' instance.
>    liftData :: Data a => a -> Q Exp
>    liftData = dataToExpQ (const Nothing)
>
> I don't really know which submodule this should come from;
> since it uses 'dataToExpQ', you might put it in Language.Haskell.TH.Quote
> but arguably 'dataToExpQ' doesn't belong in this module either,
> and it only lives there because it is a useful function for defining
> quasiquoters and it was described in the quasiquoting paper.
>
> I might propose getting rid of the 'Lift' class entirely, but you
> might prefer that class since it doesn't go through SYB (and have
> the attendant slowdown).
>
> This mode of use of 'dataToExpQ' deserves more attention.
>
> Discussion period: 1 month
>
> Cheers,
> Edward
> _______________________________________________
> Libraries mailing list
> [hidden email]
> http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries

_______________________________________________
Libraries mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
Reply | Threaded
Open this post in threaded view
|

Re: Proposal: liftData for Template Haskell

Michael Sloan
In reply to this post by Edward Z. Yang
+1 to liftData

Removing 'Lift' altogether definitely isn't the way to go, though. As Richard points out, we want to be able to lift more than just ADTs.  Also ADTs which hide their implementation can have either opaque Data instances, no Data instance, or Data instances which involve using functions for constructors.

An example of the latter is Data.Map.Map's Data instance, which uses 'fromList' as a constructor.  This results in $(dataToExpQ (\_ -> Nothing) (fromList [(1,2)])) causing the compiletime error "Illegal data constructor name: ‘fromList’".

I think 'dataToExpQ' and related functions should be modified to handle this case.  It should be rather easy - if the constructor Name is lowercase, generate a 'VarE' instead of a 'ConE'.  I suppose this is a separate proposal, but it came up when thinking about this proposal.

-Michael



On Fri, Apr 17, 2015 at 4:21 AM, Edward Z. Yang <[hidden email]> wrote:
I propose adding the following function to Language.Haskell.TH:

    -- | 'liftData' is a variant of 'lift' in the 'Lift' type class which
    -- works for any type with a 'Data' instance.
    liftData :: Data a => a -> Q Exp
    liftData = dataToExpQ (const Nothing)

I don't really know which submodule this should come from;
since it uses 'dataToExpQ', you might put it in Language.Haskell.TH.Quote
but arguably 'dataToExpQ' doesn't belong in this module either,
and it only lives there because it is a useful function for defining
quasiquoters and it was described in the quasiquoting paper.

I might propose getting rid of the 'Lift' class entirely, but you
might prefer that class since it doesn't go through SYB (and have
the attendant slowdown).

This mode of use of 'dataToExpQ' deserves more attention.

Discussion period: 1 month

Cheers,
Edward
_______________________________________________
Libraries mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries


_______________________________________________
Libraries mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
Reply | Threaded
Open this post in threaded view
|

Re: Proposal: liftData for Template Haskell

Petr Pudlák
In reply to this post by Edward Z. Yang

+1


Dne pá 17. 4. 2015 13:21 uživatel Edward Z. Yang <[hidden email]> napsal:
I propose adding the following function to Language.Haskell.TH:

    -- | 'liftData' is a variant of 'lift' in the 'Lift' type class which
    -- works for any type with a 'Data' instance.
    liftData :: Data a => a -> Q Exp
    liftData = dataToExpQ (const Nothing)

I don't really know which submodule this should come from;
since it uses 'dataToExpQ', you might put it in Language.Haskell.TH.Quote
but arguably 'dataToExpQ' doesn't belong in this module either,
and it only lives there because it is a useful function for defining
quasiquoters and it was described in the quasiquoting paper.

I might propose getting rid of the 'Lift' class entirely, but you
might prefer that class since it doesn't go through SYB (and have
the attendant slowdown).

This mode of use of 'dataToExpQ' deserves more attention.

Discussion period: 1 month

Cheers,
Edward
_______________________________________________
Libraries mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries

_______________________________________________
Libraries mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
Reply | Threaded
Open this post in threaded view
|

Re: Proposal: liftData for Template Haskell

Edward Z. Yang
In reply to this post by Edward Z. Yang
Hello all,

It looks like people are opposed to doing with the lift type-class.
So here is a counterproposal: mark the Lift type class as overlappable,
and define an instance:

    instance Data a => Lift a where
        ...

This is fairly desirable, since GHC will sometimes generate a call to
'lift', in which case liftData can't be manually filled in.  People
can still define efficient versions of lift.

Edward

Excerpts from Edward Z. Yang's message of 2015-04-17 04:21:16 -0700:

> I propose adding the following function to Language.Haskell.TH:
>
>     -- | 'liftData' is a variant of 'lift' in the 'Lift' type class which
>     -- works for any type with a 'Data' instance.
>     liftData :: Data a => a -> Q Exp
>     liftData = dataToExpQ (const Nothing)
>
> I don't really know which submodule this should come from;
> since it uses 'dataToExpQ', you might put it in Language.Haskell.TH.Quote
> but arguably 'dataToExpQ' doesn't belong in this module either,
> and it only lives there because it is a useful function for defining
> quasiquoters and it was described in the quasiquoting paper.
>
> I might propose getting rid of the 'Lift' class entirely, but you
> might prefer that class since it doesn't go through SYB (and have
> the attendant slowdown).
>
> This mode of use of 'dataToExpQ' deserves more attention.
>
> Discussion period: 1 month
>
> Cheers,
> Edward
_______________________________________________
Libraries mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
Reply | Threaded
Open this post in threaded view
|

Re: Proposal: liftData for Template Haskell

Edward Z. Yang
In reply to this post by Michael Sloan
Hello Michael,

The Data instance for Map is a very interesting one indeed.  Honestly, I
really hate this instance, and I really hate generating a VarE, in part
because there is no guarantee that fromList is defined in the same
module as the type definition.

But it gives a valuable clue about how dataToQa: maybe it's wrong for us
to try to directly make names based on the Constr information that is
given to us: instead, the generate TH code should be a call to /gunfold/
(with TH lifting the Constr).  Of course, this would be even more
inefficient, but maybe the optimizer can figure it out.
Unfortunately, I don't actually know how to encode an arbitrary
constructor invocation indirected through Data.

Edward

Excerpts from Michael Sloan's message of 2015-04-18 12:50:39 -0700:

> +1 to liftData
>
> Removing 'Lift' altogether definitely isn't the way to go, though. As
> Richard points out, we want to be able to lift more than just ADTs.  Also
> ADTs which hide their implementation can have either opaque Data instances,
> no Data instance, or Data instances which involve using functions for
> constructors.
>
> An example of the latter is Data.Map.Map's Data instance, which uses
> 'fromList' as a constructor.  This results in $(dataToExpQ (\_ -> Nothing)
> (fromList [(1,2)])) causing the compiletime error "Illegal data constructor
> name: ‘fromList’".
>
> I think 'dataToExpQ' and related functions should be modified to handle
> this case.  It should be rather easy - if the constructor Name is
> lowercase, generate a 'VarE' instead of a 'ConE'.  I suppose this is a
> separate proposal, but it came up when thinking about this proposal.
>
> -Michael
>
> On Fri, Apr 17, 2015 at 4:21 AM, Edward Z. Yang <[hidden email]> wrote:
>
> > I propose adding the following function to Language.Haskell.TH:
> >
> >     -- | 'liftData' is a variant of 'lift' in the 'Lift' type class which
> >     -- works for any type with a 'Data' instance.
> >     liftData :: Data a => a -> Q Exp
> >     liftData = dataToExpQ (const Nothing)
> >
> > I don't really know which submodule this should come from;
> > since it uses 'dataToExpQ', you might put it in Language.Haskell.TH.Quote
> > but arguably 'dataToExpQ' doesn't belong in this module either,
> > and it only lives there because it is a useful function for defining
> > quasiquoters and it was described in the quasiquoting paper.
> >
> > I might propose getting rid of the 'Lift' class entirely, but you
> > might prefer that class since it doesn't go through SYB (and have
> > the attendant slowdown).
> >
> > This mode of use of 'dataToExpQ' deserves more attention.
> >
> > Discussion period: 1 month
> >
> > Cheers,
> > Edward
> > _______________________________________________
> > Libraries mailing list
> > [hidden email]
> > http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
> >
_______________________________________________
Libraries mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
Reply | Threaded
Open this post in threaded view
|

Re: Proposal: liftData for Template Haskell

Adam Vogt
http://lpaste.net/1333635401797074944 is one way to use gunfold.

A few years ago, gunfold was error for Data.Map. If there were other abstract data types that had gunfold = error "gunfold", generating a VarE/ConE would be better because the failure would be at compile time instead of at run time.

Adam

On Tue, May 5, 2015 at 12:18 PM, Edward Z. Yang <[hidden email]> wrote:
Hello Michael,

The Data instance for Map is a very interesting one indeed.  Honestly, I
really hate this instance, and I really hate generating a VarE, in part
because there is no guarantee that fromList is defined in the same
module as the type definition.

But it gives a valuable clue about how dataToQa: maybe it's wrong for us
to try to directly make names based on the Constr information that is
given to us: instead, the generate TH code should be a call to /gunfold/
(with TH lifting the Constr).  Of course, this would be even more
inefficient, but maybe the optimizer can figure it out.
Unfortunately, I don't actually know how to encode an arbitrary
constructor invocation indirected through Data.

Edward

Excerpts from Michael Sloan's message of 2015-04-18 12:50:39 -0700:
> +1 to liftData
>
> Removing 'Lift' altogether definitely isn't the way to go, though. As
> Richard points out, we want to be able to lift more than just ADTs.  Also
> ADTs which hide their implementation can have either opaque Data instances,
> no Data instance, or Data instances which involve using functions for
> constructors.
>
> An example of the latter is Data.Map.Map's Data instance, which uses
> 'fromList' as a constructor.  This results in $(dataToExpQ (\_ -> Nothing)
> (fromList [(1,2)])) causing the compiletime error "Illegal data constructor
> name: ‘fromList’".
>
> I think 'dataToExpQ' and related functions should be modified to handle
> this case.  It should be rather easy - if the constructor Name is
> lowercase, generate a 'VarE' instead of a 'ConE'.  I suppose this is a
> separate proposal, but it came up when thinking about this proposal.
>
> -Michael
>
> On Fri, Apr 17, 2015 at 4:21 AM, Edward Z. Yang <[hidden email]> wrote:
>
> > I propose adding the following function to Language.Haskell.TH:
> >
> >     -- | 'liftData' is a variant of 'lift' in the 'Lift' type class which
> >     -- works for any type with a 'Data' instance.
> >     liftData :: Data a => a -> Q Exp
> >     liftData = dataToExpQ (const Nothing)
> >
> > I don't really know which submodule this should come from;
> > since it uses 'dataToExpQ', you might put it in Language.Haskell.TH.Quote
> > but arguably 'dataToExpQ' doesn't belong in this module either,
> > and it only lives there because it is a useful function for defining
> > quasiquoters and it was described in the quasiquoting paper.
> >
> > I might propose getting rid of the 'Lift' class entirely, but you
> > might prefer that class since it doesn't go through SYB (and have
> > the attendant slowdown).
> >
> > This mode of use of 'dataToExpQ' deserves more attention.
> >
> > Discussion period: 1 month
> >
> > Cheers,
> > Edward
> > _______________________________________________
> > Libraries mailing list
> > [hidden email]
> > http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
> >
_______________________________________________
Libraries mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries


_______________________________________________
Libraries mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
Reply | Threaded
Open this post in threaded view
|

Re: Proposal: liftData for Template Haskell

Ganesh Sittampalam
In reply to this post by Edward Z. Yang
-1: I think that kind of instance (Foo a => Bar a) is generally quite
problematic so there should be a pretty strong case to support it.

There can only be one of them - if some other class shows up that can
also provide an equally good implementation of 'lift', there's a conflict.

Also won't people get misleading error messages, implying they should
implement Data when Lift would do?

"instance Lift X where lift = liftData" doesn't seem too onerous to
write by hand to me, though I guess it may be hard to discover that's an
option.

On 05/05/2015 04:36, Edward Z. Yang wrote:

> Hello all,
>
> It looks like people are opposed to doing with the lift type-class.
> So here is a counterproposal: mark the Lift type class as overlappable,
> and define an instance:
>
>     instance Data a => Lift a where
>         ...
>
> This is fairly desirable, since GHC will sometimes generate a call to
> 'lift', in which case liftData can't be manually filled in.  People
> can still define efficient versions of lift.
>
> Edward
>
> Excerpts from Edward Z. Yang's message of 2015-04-17 04:21:16 -0700:
>> I propose adding the following function to Language.Haskell.TH:
>>
>>     -- | 'liftData' is a variant of 'lift' in the 'Lift' type class which
>>     -- works for any type with a 'Data' instance.
>>     liftData :: Data a => a -> Q Exp
>>     liftData = dataToExpQ (const Nothing)
>>
>> I don't really know which submodule this should come from;
>> since it uses 'dataToExpQ', you might put it in Language.Haskell.TH.Quote
>> but arguably 'dataToExpQ' doesn't belong in this module either,
>> and it only lives there because it is a useful function for defining
>> quasiquoters and it was described in the quasiquoting paper.
>>
>> I might propose getting rid of the 'Lift' class entirely, but you
>> might prefer that class since it doesn't go through SYB (and have
>> the attendant slowdown).
>>
>> This mode of use of 'dataToExpQ' deserves more attention.
>>
>> Discussion period: 1 month
>>
>> Cheers,
>> Edward
> _______________________________________________
> Libraries mailing list
> [hidden email]
> http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
>

_______________________________________________
Libraries mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
Reply | Threaded
Open this post in threaded view
|

Re: Proposal: liftData for Template Haskell

Gershom Bazerman
On May 13, 2015 at 2:15:26 AM, Ganesh Sittampalam ([hidden email]) wrote:

> -1: I think that kind of instance (Foo a => Bar a) is generally quite
> problematic so there should be a pretty strong case to support it.
>  
> There can only be one of them - if some other class shows up that can
> also provide an equally good implementation of 'lift', there's a conflict.
>  
> Also won't people get misleading error messages, implying they should
> implement Data when Lift would do?
>  
> "instance Lift X where lift = liftData" doesn't seem too onerous to
> write by hand to me, though I guess it may be hard to discover that's an
> option.

Isn’t this a case where -XDefaultSignatures and -XDeriveAnyClass can make things at least a bit nicer? Of course we still need to document well how to use them, but such instrumentation of the Lift class would at least make it clear that it is “intended” to be used in such a fashion :-)

-g

> On 05/05/2015 04:36, Edward Z. Yang wrote:
> > Hello all,
> >
> > It looks like people are opposed to doing with the lift type-class.
> > So here is a counterproposal: mark the Lift type class as overlappable,
> > and define an instance:
> >
> > instance Data a => Lift a where
> > ...
> >
> > This is fairly desirable, since GHC will sometimes generate a call to
> > 'lift', in which case liftData can't be manually filled in. People
> > can still define efficient versions of lift.
> >
> > Edward
> >
> > Excerpts from Edward Z. Yang's message of 2015-04-17 04:21:16 -0700:
> >> I propose adding the following function to Language.Haskell.TH:
> >>
> >> -- | 'liftData' is a variant of 'lift' in the 'Lift' type class which
> >> -- works for any type with a 'Data' instance.
> >> liftData :: Data a => a -> Q Exp
> >> liftData = dataToExpQ (const Nothing)
> >>
> >> I don't really know which submodule this should come from;
> >> since it uses 'dataToExpQ', you might put it in Language.Haskell.TH.Quote
> >> but arguably 'dataToExpQ' doesn't belong in this module either,
> >> and it only lives there because it is a useful function for defining
> >> quasiquoters and it was described in the quasiquoting paper.
> >>
> >> I might propose getting rid of the 'Lift' class entirely, but you
> >> might prefer that class since it doesn't go through SYB (and have
> >> the attendant slowdown).
> >>
> >> This mode of use of 'dataToExpQ' deserves more attention.
> >>
> >> Discussion period: 1 month
> >>
> >> Cheers,
> >> Edward
> > _______________________________________________
> > Libraries mailing list
> > [hidden email]
> > http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
> >
>  
> _______________________________________________
> Libraries mailing list
> [hidden email]
> http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
>  

_______________________________________________
Libraries mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
Reply | Threaded
Open this post in threaded view
|

Re: Proposal: liftData for Template Haskell

Edward Kmett-2
I'm very much +1 to the addition of liftData, but pretty strongly -1 on the notion of using an overlappable instance for Data a => Lift a. I really don't like encouraging that practice, orphans then start changing behavior in ways that make me deeply uncomfortable.

On the other hand, placing a default signature:

class Lift a where
  lift :: a -> Q Exp
  default lift :: Data a => a -> Q Exp
  lift = liftData

would be something I'd be 100% behind, in addition to adding the explicit liftData export.  It'd rather sharply reduce the pain of defining Lift instances and I was actually surprised it wasn't there.

-Edward

On Wed, May 13, 2015 at 2:28 AM, Gershom B <[hidden email]> wrote:
On May 13, 2015 at 2:15:26 AM, Ganesh Sittampalam ([hidden email]) wrote:
> -1: I think that kind of instance (Foo a => Bar a) is generally quite
> problematic so there should be a pretty strong case to support it.
>
> There can only be one of them - if some other class shows up that can
> also provide an equally good implementation of 'lift', there's a conflict.
>
> Also won't people get misleading error messages, implying they should
> implement Data when Lift would do?
>
> "instance Lift X where lift = liftData" doesn't seem too onerous to
> write by hand to me, though I guess it may be hard to discover that's an
> option.

Isn’t this a case where -XDefaultSignatures and -XDeriveAnyClass can make things at least a bit nicer? Of course we still need to document well how to use them, but such instrumentation of the Lift class would at least make it clear that it is “intended” to be used in such a fashion :-)

-g

> On 05/05/2015 04:36, Edward Z. Yang wrote:
> > Hello all,
> >
> > It looks like people are opposed to doing with the lift type-class.
> > So here is a counterproposal: mark the Lift type class as overlappable,
> > and define an instance:
> >
> > instance Data a => Lift a where
> > ...
> >
> > This is fairly desirable, since GHC will sometimes generate a call to
> > 'lift', in which case liftData can't be manually filled in. People
> > can still define efficient versions of lift.
> >
> > Edward
> >
> > Excerpts from Edward Z. Yang's message of 2015-04-17 04:21:16 -0700:
> >> I propose adding the following function to Language.Haskell.TH:
> >>
> >> -- | 'liftData' is a variant of 'lift' in the 'Lift' type class which
> >> -- works for any type with a 'Data' instance.
> >> liftData :: Data a => a -> Q Exp
> >> liftData = dataToExpQ (const Nothing)
> >>
> >> I don't really know which submodule this should come from;
> >> since it uses 'dataToExpQ', you might put it in Language.Haskell.TH.Quote
> >> but arguably 'dataToExpQ' doesn't belong in this module either,
> >> and it only lives there because it is a useful function for defining
> >> quasiquoters and it was described in the quasiquoting paper.
> >>
> >> I might propose getting rid of the 'Lift' class entirely, but you
> >> might prefer that class since it doesn't go through SYB (and have
> >> the attendant slowdown).
> >>
> >> This mode of use of 'dataToExpQ' deserves more attention.
> >>
> >> Discussion period: 1 month
> >>
> >> Cheers,
> >> Edward
> > _______________________________________________
> > Libraries mailing list
> > [hidden email]
> > http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
> >
>
> _______________________________________________
> Libraries mailing list
> [hidden email]
> http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
>

_______________________________________________
Libraries mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries


_______________________________________________
Libraries mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
Reply | Threaded
Open this post in threaded view
|

Re: Proposal: liftData for Template Haskell

Merijn Verstraaten
Is there any reason we can't have GHC derive Lift instance automatically? I know there's already a TH library for this, but I guess I don't see why GHC can't derive them for us. Additionally, the lack of lift instances is really a pain for a lot of compile time evaluation tricks.

Cheers,
Merijn

> On 13 May 2015, at 11:40, Edward Kmett <[hidden email]> wrote:
>
> I'm very much +1 to the addition of liftData, but pretty strongly -1 on the notion of using an overlappable instance for Data a => Lift a. I really don't like encouraging that practice, orphans then start changing behavior in ways that make me deeply uncomfortable.
>
> On the other hand, placing a default signature:
>
> class Lift a where
>   lift :: a -> Q Exp
>   default lift :: Data a => a -> Q Exp
>   lift = liftData
>
> would be something I'd be 100% behind, in addition to adding the explicit liftData export.  It'd rather sharply reduce the pain of defining Lift instances and I was actually surprised it wasn't there.
>
> -Edward
>
> On Wed, May 13, 2015 at 2:28 AM, Gershom B <[hidden email]> wrote:
> On May 13, 2015 at 2:15:26 AM, Ganesh Sittampalam ([hidden email]) wrote:
> > -1: I think that kind of instance (Foo a => Bar a) is generally quite
> > problematic so there should be a pretty strong case to support it.
> >
> > There can only be one of them - if some other class shows up that can
> > also provide an equally good implementation of 'lift', there's a conflict.
> >
> > Also won't people get misleading error messages, implying they should
> > implement Data when Lift would do?
> >
> > "instance Lift X where lift = liftData" doesn't seem too onerous to
> > write by hand to me, though I guess it may be hard to discover that's an
> > option.
>
> Isn’t this a case where -XDefaultSignatures and -XDeriveAnyClass can make things at least a bit nicer? Of course we still need to document well how to use them, but such instrumentation of the Lift class would at least make it clear that it is “intended” to be used in such a fashion :-)
>
> -g
>
> > On 05/05/2015 04:36, Edward Z. Yang wrote:
> > > Hello all,
> > >
> > > It looks like people are opposed to doing with the lift type-class.
> > > So here is a counterproposal: mark the Lift type class as overlappable,
> > > and define an instance:
> > >
> > > instance Data a => Lift a where
> > > ...
> > >
> > > This is fairly desirable, since GHC will sometimes generate a call to
> > > 'lift', in which case liftData can't be manually filled in. People
> > > can still define efficient versions of lift.
> > >
> > > Edward
> > >
> > > Excerpts from Edward Z. Yang's message of 2015-04-17 04:21:16 -0700:
> > >> I propose adding the following function to Language.Haskell.TH:
> > >>
> > >> -- | 'liftData' is a variant of 'lift' in the 'Lift' type class which
> > >> -- works for any type with a 'Data' instance.
> > >> liftData :: Data a => a -> Q Exp
> > >> liftData = dataToExpQ (const Nothing)
> > >>
> > >> I don't really know which submodule this should come from;
> > >> since it uses 'dataToExpQ', you might put it in Language.Haskell.TH.Quote
> > >> but arguably 'dataToExpQ' doesn't belong in this module either,
> > >> and it only lives there because it is a useful function for defining
> > >> quasiquoters and it was described in the quasiquoting paper.
> > >>
> > >> I might propose getting rid of the 'Lift' class entirely, but you
> > >> might prefer that class since it doesn't go through SYB (and have
> > >> the attendant slowdown).
> > >>
> > >> This mode of use of 'dataToExpQ' deserves more attention.
> > >>
> > >> Discussion period: 1 month
> > >>
> > >> Cheers,
> > >> Edward
> > > _______________________________________________
> > > Libraries mailing list
> > > [hidden email]
> > > http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
> > >
> >
> > _______________________________________________
> > Libraries mailing list
> > [hidden email]
> > http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
> >
>
> _______________________________________________
> Libraries mailing list
> [hidden email]
> http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
>
> _______________________________________________
> Libraries mailing list
> [hidden email]
> http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries

_______________________________________________
Libraries mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries

signature.asc (859 bytes) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: Proposal: liftData for Template Haskell

Richard Eisenberg-2
On May 13, 2015, at 6:13 AM, Merijn Verstraaten <[hidden email]> wrote:

> Is there any reason we can't have GHC derive Lift instance automatically? I know there's already a TH library for this, but I guess I don't see why GHC can't derive them for us. Additionally, the lack of lift instances is really a pain for a lot of compile time evaluation tricks.

GHC *could* do this automatically, but I don't think it *should*. `Lift` is far enough out of the way that I don't think there should be built-in compiler support for it. Doing it in a library is enough.

But, DeriveAnyClass + DefaultSignatures can make it feel like GHC is doing it for you. That is, if we have

> class Lift a where
>  lift :: a -> Q Exp
>  default lift :: Data a => a -> Q Exp
>  lift = liftData


(as previously proposed) and you have -XDeriveAnyClass turned on, then you can say

> data Foo a = K1 Int Bool | K2 | K3 a
>   deriving Lift

and it should Just Work.

Richard


>
> Cheers,
> Merijn
>
>> On 13 May 2015, at 11:40, Edward Kmett <[hidden email]> wrote:
>>
>> I'm very much +1 to the addition of liftData, but pretty strongly -1 on the notion of using an overlappable instance for Data a => Lift a. I really don't like encouraging that practice, orphans then start changing behavior in ways that make me deeply uncomfortable.
>>
>> On the other hand, placing a default signature:
>>
>> class Lift a where
>>  lift :: a -> Q Exp
>>  default lift :: Data a => a -> Q Exp
>>  lift = liftData
>>
>> would be something I'd be 100% behind, in addition to adding the explicit liftData export.  It'd rather sharply reduce the pain of defining Lift instances and I was actually surprised it wasn't there.
>>
>> -Edward
>>
>> On Wed, May 13, 2015 at 2:28 AM, Gershom B <[hidden email]> wrote:
>> On May 13, 2015 at 2:15:26 AM, Ganesh Sittampalam ([hidden email]) wrote:
>>> -1: I think that kind of instance (Foo a => Bar a) is generally quite
>>> problematic so there should be a pretty strong case to support it.
>>>
>>> There can only be one of them - if some other class shows up that can
>>> also provide an equally good implementation of 'lift', there's a conflict.
>>>
>>> Also won't people get misleading error messages, implying they should
>>> implement Data when Lift would do?
>>>
>>> "instance Lift X where lift = liftData" doesn't seem too onerous to
>>> write by hand to me, though I guess it may be hard to discover that's an
>>> option.
>>
>> Isn’t this a case where -XDefaultSignatures and -XDeriveAnyClass can make things at least a bit nicer? Of course we still need to document well how to use them, but such instrumentation of the Lift class would at least make it clear that it is “intended” to be used in such a fashion :-)
>>
>> -g
>>
>>> On 05/05/2015 04:36, Edward Z. Yang wrote:
>>>> Hello all,
>>>>
>>>> It looks like people are opposed to doing with the lift type-class.
>>>> So here is a counterproposal: mark the Lift type class as overlappable,
>>>> and define an instance:
>>>>
>>>> instance Data a => Lift a where
>>>> ...
>>>>
>>>> This is fairly desirable, since GHC will sometimes generate a call to
>>>> 'lift', in which case liftData can't be manually filled in. People
>>>> can still define efficient versions of lift.
>>>>
>>>> Edward
>>>>
>>>> Excerpts from Edward Z. Yang's message of 2015-04-17 04:21:16 -0700:
>>>>> I propose adding the following function to Language.Haskell.TH:
>>>>>
>>>>> -- | 'liftData' is a variant of 'lift' in the 'Lift' type class which
>>>>> -- works for any type with a 'Data' instance.
>>>>> liftData :: Data a => a -> Q Exp
>>>>> liftData = dataToExpQ (const Nothing)
>>>>>
>>>>> I don't really know which submodule this should come from;
>>>>> since it uses 'dataToExpQ', you might put it in Language.Haskell.TH.Quote
>>>>> but arguably 'dataToExpQ' doesn't belong in this module either,
>>>>> and it only lives there because it is a useful function for defining
>>>>> quasiquoters and it was described in the quasiquoting paper.
>>>>>
>>>>> I might propose getting rid of the 'Lift' class entirely, but you
>>>>> might prefer that class since it doesn't go through SYB (and have
>>>>> the attendant slowdown).
>>>>>
>>>>> This mode of use of 'dataToExpQ' deserves more attention.
>>>>>
>>>>> Discussion period: 1 month
>>>>>
>>>>> Cheers,
>>>>> Edward
>>>> _______________________________________________
>>>> Libraries mailing list
>>>> [hidden email]
>>>> http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
>>>>
>>>
>>> _______________________________________________
>>> Libraries mailing list
>>> [hidden email]
>>> http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
>>>
>>
>> _______________________________________________
>> Libraries mailing list
>> [hidden email]
>> http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
>>
>> _______________________________________________
>> Libraries mailing list
>> [hidden email]
>> http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
>
> _______________________________________________
> Libraries mailing list
> [hidden email]
> http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries

_______________________________________________
Libraries mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
Reply | Threaded
Open this post in threaded view
|

Re: Proposal: liftData for Template Haskell

Adam Vogt
In reply to this post by Merijn Verstraaten
On Wed, May 13, 2015 at 6:13 AM, Merijn Verstraaten <[hidden email]> wrote:
>
> Is there any reason we can't have GHC derive Lift instance automatically? I know there's already a TH library for this, but I guess I don't see why GHC can't derive them for us. Additionally, the lack of lift instances is really a pain for a lot of compile time evaluation tricks.

There are two libraries to get your orphan Lift instances: th-orphans and th-lift-instances.

Here's a list of what should be all the Lift instances on hackage: <http://code.haskell.org/~aavogt/lift_instances_hackage.txt>. There are many duplicates. Text and Double instances happen quite often (9 in ~ 715 packages depending on template-haskell):

Text (Lazy or Strict)
  ./aeson-schema-0.3.0.5/src/Data/Aeson/TH/Lift.hs
  ./parse-help-0.0/System/Console/ParseHelp.hs
  ./ssh-0.3.1/test/EmbedTree.hs
  ./SimpleLog-0.1.0.3/src/System/Log/SLog/Format.hs
  ./persistent-template-2.1.3/Database/Persist/TH.hs -- indirectly via a Lift' class
  ./th-lift-instances-0.1.5/src/Instances/TH/Lift.hs
  ./typedquery-0.1.0.2/src/Database/TypedQuery/Types.hs
  ./haskhol-core-1.1.0/src/HaskHOL/Core/Kernel/Prims.hs
  ./lighttpd-conf-0.4/src/Lighttpd/Conf/Instances/Lift.hs
  ./yaml-rpc-1.0.3/Network/YAML/API.hs

Double
  ./aeson-schema-0.3.0.5/src/Data/Aeson/TH/Lift.hs
  ./th-orphans-0.11.1/src/Language/Haskell/TH/Instances.hs
  ./paragon-0.1.28/src/Language/Java/Paragon/QuasiQuoter/Lift.hs
  ./ta-0.1/Database/TA/Helper/LiftQ.hs
  ./CCA-0.1.5.3/src/Language/Haskell/TH/Instances.hs
  ./th-lift-instances-0.1.5/src/Instances/TH/Lift.hs
  ./llvm-general-quote-0.2.0.0/src/LLVM/General/Quote/AST.hs
  ./Eq-1.1.3/Language/Eq/Quasiquote.hs
  ./ivory-0.1.0.0/src/Ivory/Language/Syntax/AST.hs


Those orphans could be removed if we had instance Data a => Lift a, because those types have a mostly sane Data instance. While there are some differences in the Double instances:

lift x = [| read $(lift (show x)) |] -- in ./paragon-0.1.28/src/Language/Java/Paragon/QuasiQuoter/Lift.hs

lift d = [| D# $(return (LitE (DoublePrimL (toRational d)))) |]

lift d = [| fromRational $(litE . rationalL . toRational $ d) :: Double |]

lift = lift . toRational

$(lift (0/0)) is wrong for most instances already: going through Rational gives -Infinity. Incidentally dataToExpQ (const Nothing) (0/0) also gives -Infinity.

Another difference is whether :t $(lift (1.0 :: Double)) is Double, Fractional a => a, Read a => a, or something else.

Apart from those two issues, it seems that the duplicated Lift instances do the same thing as liftData, so the "adding an import will change the program's runtime behavior" seems rare compared with "adding an import breaks your program because we didn't agree to put the orphans in one package only".

So I'm:

+1 on Data a => Lift a
+1 on the DefaultSignatures, if the overlapping instance won't happen




_______________________________________________
Libraries mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries