deepseq: instance NFData (a -> b)

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

deepseq: instance NFData (a -> b)

Henning Thielemann

According to Haddock comments, between deepseq-1.2 and deepseq-1.3 an
instance for NFData on functions was introduced without previous
discussion. I find this instance pretty problematic since it has no
superclasses. The correct instance would be certainly something like

instance (Enumerate a, NFData b) => NFData (a -> b)

where Enumerate would be a new class that allows to enumerate all values
of a type. This would be hardly useful because it is pretty inefficient.
I'd prefer that the instance is removed, again, or even better, be
replaced by a non-implementable instance. Alternatively we should replace
it by a correct implementation with corresponding superclasses. If we do
the second, then we could still omit the Enumerate instance for types
where enumeration of all values of the type is too expensive.

I assume that the instance was added to simplify automatic derivation of
NFData instances. However, I think it would be better if people insert
custom deepseq implementation for the expected functions then.
_______________________________________________
Libraries mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
Reply | Threaded
Open this post in threaded view
|

Re: deepseq: instance NFData (a -> b)

Boespflug, Mathieu
+1

This instance doesn't make much sense (to me at least) and is pretty
problematic for apps that use NFData constraints as evidence that
values are ground and fully evaluated (hence don't capture arbitrary
resources). In HaskellR we use NFData constraints to make sure only
fully evaluated ground data escapes the scope of a region. But
functions are not a first-order values. They can leak arbitrary
resources out of the scope of a region.
--
Mathieu Boespflug
Founder at http://tweag.io.


On 1 May 2016 at 16:38, Henning Thielemann
<[hidden email]> wrote:

>
> According to Haddock comments, between deepseq-1.2 and deepseq-1.3 an
> instance for NFData on functions was introduced without previous discussion.
> I find this instance pretty problematic since it has no superclasses. The
> correct instance would be certainly something like
>
> instance (Enumerate a, NFData b) => NFData (a -> b)
>
> where Enumerate would be a new class that allows to enumerate all values of
> a type. This would be hardly useful because it is pretty inefficient. I'd
> prefer that the instance is removed, again, or even better, be replaced by a
> non-implementable instance. Alternatively we should replace it by a correct
> implementation with corresponding superclasses. If we do the second, then we
> could still omit the Enumerate instance for types where enumeration of all
> values of the type is too expensive.
>
> I assume that the instance was added to simplify automatic derivation of
> NFData instances. However, I think it would be better if people insert
> custom deepseq implementation for the expected functions then.
> _______________________________________________
> 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: deepseq: instance NFData (a -> b)

Michael Walker
In reply to this post by Henning Thielemann
It depends on what you mean when you say a function is in normal form.
Unfortunately the instance doesn't capture either of the definitions
that immediately come to my mind:

- All values it returns are in normal form? This requires an NFData b
  constraint.
- The body of the function is in normal form? This requires HNF, which
  we don't have in Haskell. I guess the current instance is going for
  this, but approximates HNF with WHNF.

I'm +1 to removing this, simply because there are at least three
(including yours) reasonable definitions. If someone wants an NFData
instance for a value which includes functions, they should know exactly
how they want to handle that.

On Sun, 1 May 2016 16:38:07 +0200 (CEST)
Henning Thielemann <[hidden email]> wrote:

> According to Haddock comments, between deepseq-1.2 and deepseq-1.3 an
> instance for NFData on functions was introduced without previous
> discussion. I find this instance pretty problematic since it has no
> superclasses. The correct instance would be certainly something like
>
> instance (Enumerate a, NFData b) => NFData (a -> b)
>
> where Enumerate would be a new class that allows to enumerate all
> values of a type. This would be hardly useful because it is pretty
> inefficient. I'd prefer that the instance is removed, again, or even
> better, be replaced by a non-implementable instance. Alternatively we
> should replace it by a correct implementation with corresponding
> superclasses. If we do the second, then we could still omit the
> Enumerate instance for types where enumeration of all values of the
> type is too expensive.
>
> I assume that the instance was added to simplify automatic derivation
> of NFData instances. However, I think it would be better if people
> insert custom deepseq implementation for the expected functions then.
> _______________________________________________
> Libraries mailing list
> [hidden email]
> http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
--
Michael Walker (http://www.barrucadu.co.uk)

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

attachment0 (836 bytes) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: deepseq: instance NFData (a -> b)

Herbert Valerio Riedel-3
In reply to this post by Boespflug, Mathieu
On 2016-05-01 at 16:51:45 +0200, Boespflug, Mathieu wrote:

[...]

> This instance doesn't make much sense (to me at least) and is pretty
> problematic for apps that use NFData constraints as evidence that
> values are ground and fully evaluated (hence don't capture arbitrary
> resources). In HaskellR we use NFData constraints to make sure only
> fully evaluated ground data escapes the scope of a region. But
> functions are not a first-order values. They can leak arbitrary
> resources out of the scope of a region.

Are the recently added NFData instances for IORef/MVar problematic as
well?

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

Re: deepseq: instance NFData (a -> b)

Niklas Hambüchen
In reply to this post by Henning Thielemann
I wound find it interesting to learn what exactly will break when this
instance is removed / what feature motivated the addition of the einstance.

I'm taking a guess here, maybe it's Generics based deriving?

    data D = D { something :: Int, somethingElse :: Int -> String }
      deriving Generic

    deriving instance NFData D

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

Re: deepseq: instance NFData (a -> b)

Boespflug, Mathieu
In reply to this post by Herbert Valerio Riedel-3
On 1 May 2016 at 17:00, Herbert Valerio Riedel <[hidden email]> wrote:

> On 2016-05-01 at 16:51:45 +0200, Boespflug, Mathieu wrote:
>
> [...]
>
>> This instance doesn't make much sense (to me at least) and is pretty
>> problematic for apps that use NFData constraints as evidence that
>> values are ground and fully evaluated (hence don't capture arbitrary
>> resources). In HaskellR we use NFData constraints to make sure only
>> fully evaluated ground data escapes the scope of a region. But
>> functions are not a first-order values. They can leak arbitrary
>> resources out of the scope of a region.
>
> Are the recently added NFData instances for IORef/MVar problematic as
> well?

I guess so, yes!

These 3 instances, along with the STRef one, strike me as antithetical
to the purpose stated at the top of the DeepSeq module:

"A typical use is to prevent resource leaks in lazy IO programs,
[...]. Another common use is to ensure any exceptions hidden within
lazy fields of a data structure do not leak outside the scope of the
exception handler, or to force evaluation of a data structure in one
thread, before passing to another thread (preventing work moving to
the wrong threads)."

Or perhaps - we should at the very clarify and characterize precisely
what invariants NFData instances are or are not expected to enforce?
_______________________________________________
Libraries mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
Reply | Threaded
Open this post in threaded view
|

Re: deepseq: instance NFData (a -> b)

David Feuer
In reply to this post by Herbert Valerio Riedel-3
I say no. An `IORef` is just a pointer, and forcing one to NF means
quite simply that you determine exactly where it points, which is
completely different from forcing whatever happens to be on the other
end. A function seems much more problematic.

On Sun, May 1, 2016 at 11:00 AM, Herbert Valerio Riedel
<[hidden email]> wrote:

> On 2016-05-01 at 16:51:45 +0200, Boespflug, Mathieu wrote:
>
> [...]
>
>> This instance doesn't make much sense (to me at least) and is pretty
>> problematic for apps that use NFData constraints as evidence that
>> values are ground and fully evaluated (hence don't capture arbitrary
>> resources). In HaskellR we use NFData constraints to make sure only
>> fully evaluated ground data escapes the scope of a region. But
>> functions are not a first-order values. They can leak arbitrary
>> resources out of the scope of a region.
>
> Are the recently added NFData instances for IORef/MVar problematic as
> well?
>
> -- hvr
> _______________________________________________
> 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: deepseq: instance NFData (a -> b)

Dan Doel
In reply to this post by Michael Walker
On Sun, May 1, 2016 at 10:58 AM, Michael Walker <[hidden email]> wrote:
> It depends on what you mean when you say a function is in normal form.
> Unfortunately the instance doesn't capture either of the definitions
> that immediately come to my mind:
>
> - All values it returns are in normal form? This requires an NFData b
>   constraint.

Even when talking about term rewriting, reducing an application of two
normal forms does not necessarily yield a normal form directly.

> - The body of the function is in normal form? This requires HNF, which
>   we don't have in Haskell. I guess the current instance is going for
>   this, but approximates HNF with WHNF.

Requiring the body to be in normal form would actually be normal form.
Head normal form is actually a weaker condition, where the body must
not be a redex. But the distinction is rather academic, because
neither of these can easily be achieved in GHC.

Anyhow, I would suggest not getting hung up on what 'normal form'
means, because it is actually just a bad name for what is going on
once functions are involved. Really, that's why the class is named
`NFData` in my mind, because talking about what it does as being the
'normal form' only really makes sense when you're talking about pure,
sum-of-products algebraic data, and functions are not that.

The more important question is, what is desirable behavior, and why?
Why would enumerating all possible results of a function and deep
seqing them be the desired behavior of deep seqing a function? It
doesn't necessarily, for instance, have the sort of, 'pull everything
into memory to free another scarce resource,' effect mentioned,
because functions don't work that way.

I would guess that the main argument for this behavior is to say that
it is the only 'allowed' behavior, but, being useless, it should just
be removed. But it would be better to argue that the instance should
be removed directly.

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

Re: deepseq: instance NFData (a -> b)

Ryan Scott
In reply to this post by Henning Thielemann
I'm tentatively +1 on the idea of removing the NFData (a -> b) instance.

Henning raises a good point that there are probably folks who rely on
that instance to make automatic deriving of NFData. (Disclaimer: the
phrase "folks" includes myself.) A similar scenario arises when
deriving Show instances, for which a compromise was made by putting
the Text.Show.Functions module in base, which does nothing but export
an orphan Show (a -> b) instance.

Perhaps, if we wanted to retain the ability to use the NFData (a -> b)
instance in limited scenarios (e.g., when you're writing an
application and there's no risk of leaking orphan instances to other
users), then we could also introduce a Control.DeepSeq.Functions
module that exports an orphan NFData (a -> b) instance, and put a
giant warning at the top stating that such an instance should be used
responsibly. What say ye?

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

Re: deepseq: instance NFData (a -> b)

Henning Thielemann

On Fri, 6 May 2016, Ryan Scott wrote:

> Perhaps, if we wanted to retain the ability to use the NFData (a -> b)
> instance in limited scenarios (e.g., when you're writing an
> application and there's no risk of leaking orphan instances to other
> users), then we could also introduce a Control.DeepSeq.Functions
> module that exports an orphan NFData (a -> b) instance, and put a
> giant warning at the top stating that such an instance should be used
> responsibly. What say ye?

Since we got several problematic instances over time, we might also
consider my proposal of warning about these instances on user demand:
    http://mail.haskell.org/pipermail/libraries/2016-March/026859.html
    https://ghc.haskell.org/trac/ghc/ticket/11796
_______________________________________________
Libraries mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
Reply | Threaded
Open this post in threaded view
|

Re: deepseq: instance NFData (a -> b)

Edward Kmett-2
In reply to this post by Ryan Scott
I have to admit the idea of duplicating the orphan instance module we have for Text.Show.Functions makes me queasy. It is a pretty ugly compromise that makes everyone unhappy, not really a model for future behavior. I'd rather drop the instance entirely but could be convinced.

Sent from my iPad

> On May 6, 2016, at 11:56 AM, Ryan Scott <[hidden email]> wrote:
>
> I'm tentatively +1 on the idea of removing the NFData (a -> b) instance.
>
> Henning raises a good point that there are probably folks who rely on
> that instance to make automatic deriving of NFData. (Disclaimer: the
> phrase "folks" includes myself.) A similar scenario arises when
> deriving Show instances, for which a compromise was made by putting
> the Text.Show.Functions module in base, which does nothing but export
> an orphan Show (a -> b) instance.
>
> Perhaps, if we wanted to retain the ability to use the NFData (a -> b)
> instance in limited scenarios (e.g., when you're writing an
> application and there's no risk of leaking orphan instances to other
> users), then we could also introduce a Control.DeepSeq.Functions
> module that exports an orphan NFData (a -> b) instance, and put a
> giant warning at the top stating that such an instance should be used
> responsibly. What say ye?
>
> Ryan S.
> _______________________________________________
> 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: deepseq: instance NFData (a -> b)

Ryan Scott

I wouldn't be sad to see the instance go, although I do extract a minimal amount of utility out of it. In any case, I doubt I'm going to convince anyone, so let's just remove it :)

Ryan S.

On May 6, 2016 5:52 PM, "Edward Kmett" <[hidden email]> wrote:
I have to admit the idea of duplicating the orphan instance module we have for Text.Show.Functions makes me queasy. It is a pretty ugly compromise that makes everyone unhappy, not really a model for future behavior. I'd rather drop the instance entirely but could be convinced.

Sent from my iPad

> On May 6, 2016, at 11:56 AM, Ryan Scott <[hidden email]> wrote:
>
> I'm tentatively +1 on the idea of removing the NFData (a -> b) instance.
>
> Henning raises a good point that there are probably folks who rely on
> that instance to make automatic deriving of NFData. (Disclaimer: the
> phrase "folks" includes myself.) A similar scenario arises when
> deriving Show instances, for which a compromise was made by putting
> the Text.Show.Functions module in base, which does nothing but export
> an orphan Show (a -> b) instance.
>
> Perhaps, if we wanted to retain the ability to use the NFData (a -> b)
> instance in limited scenarios (e.g., when you're writing an
> application and there's no risk of leaking orphan instances to other
> users), then we could also introduce a Control.DeepSeq.Functions
> module that exports an orphan NFData (a -> b) instance, and put a
> giant warning at the top stating that such an instance should be used
> responsibly. What say ye?
>
> Ryan S.
> _______________________________________________
> 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: deepseq: instance NFData (a -> b)

Bardur Arantsson-2
In reply to this post by Edward Kmett-2
On 05/06/2016 11:52 PM, Edward Kmett wrote:
> I have to admit the idea of duplicating the orphan instance module we
> have for Text.Show.Functions makes me queasy. It is a pretty ugly
compromise
> that makes everyone unhappy, not really a model for future behavior.
I'd rather
> drop the instance entirely but could be convinced.
>

+1

KILL IT! KILL IT WITH FIRE!... ahem.

Regards,

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

Re: deepseq: instance NFData (a -> b)

Edward Kmett-2
Let's turn this around, is there anybody actually in favor of keeping
the instance?

On Sat, May 7, 2016 at 4:05 AM, Bardur Arantsson <[hidden email]> wrote:

> On 05/06/2016 11:52 PM, Edward Kmett wrote:
>> I have to admit the idea of duplicating the orphan instance module we
>> have for Text.Show.Functions makes me queasy. It is a pretty ugly
> compromise
>> that makes everyone unhappy, not really a model for future behavior.
> I'd rather
>> drop the instance entirely but could be convinced.
>>
>
> +1
>
> KILL IT! KILL IT WITH FIRE!... ahem.
>
> Regards,
>
> _______________________________________________
> 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: deepseq: instance NFData (a -> b)

Henning Thielemann

On Sat, 7 May 2016, Edward Kmett wrote:

> Let's turn this around, is there anybody actually in favor of keeping
> the instance?

Looking in the git-logs I found git-commit
3b5c957ce7bba7b63b4483a43c6762c3f5d8ee28 by Herbert Valerio Riedel saying:

"Merge `deepseq-generics` into `deepseq` ..."

and it points to the proposal:
    http://permalink.gmane.org/gmane.comp.lang.haskell.libraries/23031


So, I guess Herbert must be in favor of the instance because he added it.
:-)

And this commit confirms that the instance NFData (a->b) was a side
product of Generics support.
_______________________________________________
Libraries mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries