Fwd: lazier writer monad

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

Fwd: lazier writer monad

Tristan Wibberley
Dear Haskell Libraries mailing list members,

I've submitted a merge request for an increase in the laziness of the writer monad: https://gitlab.haskell.org/ghc/ghc/merge_requests/1262 and it requires discussion via this mailing list.

The link above includes an example of the motivation for this change and I hope you can all extrapolate to see the importance of this change, sufficient to not only accept this but to be moved to add a language flag, available within the content of a module's source file, to match unique constructors lazily throughout a module that uses it, lifting _|_ to the next least-defined value.

The core problem is that for the most handy and practical library interfaces, we need function results to be as well-defined as possible before a strict pattern match is required to choose between two constructors/values. There are several parts to providing that but one important part is that elements of patterns that cannot be unmatched should be lazily matched so the function's definition can be used without evaluating the function's arguments first. This avoids having to train users to always avoid patterns except after a let binding which would otherwise be necessary to establish a standard habit to lazily pattern match so the user base encourages each other to make their functions maximally useful.

--
Tristan

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

Re: lazier writer monad

Eric Mertens
Hi,

I think we should update the Applicative and Monad instances to document their strictness behaviors instead.

For code that relies on a particular strictness behavior I would recommend sticking with one of the modules in the transformers package: Control.Monad.Trans.Writer.Strict and Control.Monad.Trans.Writer.Lazy

As far as I can tell the current state of the PR updates the Applicative instance but not the Monad instance. Should this PR actually advance we should address that.

I agree that there are compositionally benefits to code that is as lazy as possible, however there are also space leak costs to that kind of code as well. I don’t think a simple rule like “as lazy as possible is best” is a good guiding principle. Changing the behavior now would just make the instance quite challenging to use portably and doesn’t make the instance more correct, just different.

Having a magic rule that datatypes with a single constructor match differently from datatypes with multiple constructors sounds like a readability nightmare. It’s already challenging to reason about the strictness behavior of programs. Making it harder like this would be a mistake. In addition adding or removing constructors from a datatype would have significant, non-local strictness effects to an existing program.

(The PR mentions something about Dependent Haskell and testing. Dependent Haskell isn’t going to replace testing and it isn’t going to make strictness easy to reason about.)

Best regards,
Eric Mertens
glguy

On Jun 26, 2019, at 12:57 PM, Tristan Wibberley <[hidden email]> wrote:

Dear Haskell Libraries mailing list members,

I've submitted a merge request for an increase in the laziness of the writer monad: https://gitlab.haskell.org/ghc/ghc/merge_requests/1262 and it requires discussion via this mailing list.

The link above includes an example of the motivation for this change and I hope you can all extrapolate to see the importance of this change, sufficient to not only accept this but to be moved to add a language flag, available within the content of a module's source file, to match unique constructors lazily throughout a module that uses it, lifting _|_ to the next least-defined value.

The core problem is that for the most handy and practical library interfaces, we need function results to be as well-defined as possible before a strict pattern match is required to choose between two constructors/values. There are several parts to providing that but one important part is that elements of patterns that cannot be unmatched should be lazily matched so the function's definition can be used without evaluating the function's arguments first. This avoids having to train users to always avoid patterns except after a let binding which would otherwise be necessary to establish a standard habit to lazily pattern match so the user base encourages each other to make their functions maximally useful.

--
Tristan
_______________________________________________
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: lazier writer monad

David Feuer
In reply to this post by Tristan Wibberley
I agree with Eric. Aside from the practically important concerns he raised, your proposed instance is not strictly lawful, which I find troubling for such an essential wired-in type.

    pure id <*> undefined
    = (mempty, id) <*> undefined
    = (mempty <> fst undefined, id undefined)
    = (undefined, undefined)

But according to the Applicative identity law,

    pure id <*> undefined = undefined

That's similar, but not the same.

Let me add that not only the Monad instance but also the Functor one is incompatible, because we require

    fmap f x = pure f <*> x

On Wed, Jun 26, 2019, 3:58 PM Tristan Wibberley <[hidden email]> wrote:
Dear Haskell Libraries mailing list members,

I've submitted a merge request for an increase in the laziness of the writer monad: https://gitlab.haskell.org/ghc/ghc/merge_requests/1262 and it requires discussion via this mailing list.

The link above includes an example of the motivation for this change and I hope you can all extrapolate to see the importance of this change, sufficient to not only accept this but to be moved to add a language flag, available within the content of a module's source file, to match unique constructors lazily throughout a module that uses it, lifting _|_ to the next least-defined value.

The core problem is that for the most handy and practical library interfaces, we need function results to be as well-defined as possible before a strict pattern match is required to choose between two constructors/values. There are several parts to providing that but one important part is that elements of patterns that cannot be unmatched should be lazily matched so the function's definition can be used without evaluating the function's arguments first. This avoids having to train users to always avoid patterns except after a let binding which would otherwise be necessary to establish a standard habit to lazily pattern match so the user base encourages each other to make their functions maximally useful.

--
Tristan
_______________________________________________
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