do-notation for building monoid values

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

do-notation for building monoid values

Olaf Klinke
Dear cafe,

prompted by a discussion with the author of blaze-markup [1] I realized a pattern and would like to know whether other haskellers have exploited this/find this useful:

For every monoid m, the types Writer m () and m are isomorphic as types via tell and execWriter. Moreover, Writer m is a monad if and only if m is a monoid. For every monad t, the type t () is a monoid with
   mempty = return ()
   mappend = (>>).
In the particular case of Writer m () and m, the isomorphism of Haskell types is in fact an isomorphism of monoids, that is, the functions tell and execWriter preserve the monoid operations.

This enables us to use do-notation in building complicated values of any monoid type, e.g. Text or any other syntax. Instead of writing

complicatedValue = component1 <>
  component2 <>
  modifier (component3 <> component4)

one can write

complicatedValue = execWriter $ do
  component1
  component2
  modifier $ do
    component3
    component4

Should such an idiom be encouraged/discouraged? How do you handle the construction of monoid values (especially text-like) with interspersed function applications (e.g. show, prettyprint)?

Regards,
Olaf

[1] https://github.com/jaspervdj/blaze-markup/issues/36
_______________________________________________
Haskell-Cafe mailing list
To (un)subscribe, modify options or view archives go to:
http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
Only members subscribed via the mailman list are allowed to post.
Reply | Threaded
Open this post in threaded view
|

Re: do-notation for building monoid values

Merijn Verstraaten
I always just use mconcat and lists, so instead of:
> complicatedValue = execWriter $ do
>  component1
>  component2
>  modifier $ do
>    component3
>    component4

I write:

complicatedValue = mconcat
    [ component1
    , component2
    , modifier . mconcat $ [component3, component4]
    ]

Alternatively, if component3 and component4 are really long or lots of them linewrap those too:

complicatedValue = mconcat
    [ component1
    , component2
    , modifier . mconcat $
        [ component3
        , component4
        ]
    ]

Cheers,
Merijn

> On 8 Mar 2018, at 14:02, Olaf Klinke <[hidden email]> wrote:
>
> Dear cafe,
>
> prompted by a discussion with the author of blaze-markup [1] I realized a pattern and would like to know whether other haskellers have exploited this/find this useful:
>
> For every monoid m, the types Writer m () and m are isomorphic as types via tell and execWriter. Moreover, Writer m is a monad if and only if m is a monoid. For every monad t, the type t () is a monoid with
>   mempty = return ()
>   mappend = (>>).
> In the particular case of Writer m () and m, the isomorphism of Haskell types is in fact an isomorphism of monoids, that is, the functions tell and execWriter preserve the monoid operations.
>
> This enables us to use do-notation in building complicated values of any monoid type, e.g. Text or any other syntax. Instead of writing
>
> complicatedValue = component1 <>
>  component2 <>
>  modifier (component3 <> component4)
>
> one can write
>
> complicatedValue = execWriter $ do
>  component1
>  component2
>  modifier $ do
>    component3
>    component4
>
> Should such an idiom be encouraged/discouraged? How do you handle the construction of monoid values (especially text-like) with interspersed function applications (e.g. show, prettyprint)?
>
> Regards,
> Olaf
>
> [1] https://github.com/jaspervdj/blaze-markup/issues/36
> _______________________________________________
> Haskell-Cafe mailing list
> To (un)subscribe, modify options or view archives go to:
> http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
> Only members subscribed via the mailman list are allowed to post.

_______________________________________________
Haskell-Cafe mailing list
To (un)subscribe, modify options or view archives go to:
http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
Only members subscribed via the mailman list are allowed to post.

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

Re: do-notation for building monoid values

Andrew Martin
I do the same thing that Merijn does. It works really well.

On Thu, Mar 8, 2018 at 8:08 AM, Merijn Verstraaten <[hidden email]> wrote:
I always just use mconcat and lists, so instead of:
> complicatedValue = execWriter $ do
>  component1
>  component2
>  modifier $ do
>    component3
>    component4

I write:

complicatedValue = mconcat
    [ component1
    , component2
    , modifier . mconcat $ [component3, component4]
    ]

Alternatively, if component3 and component4 are really long or lots of them linewrap those too:

complicatedValue = mconcat
    [ component1
    , component2
    , modifier . mconcat $
        [ component3
        , component4
        ]
    ]

Cheers,
Merijn

> On 8 Mar 2018, at 14:02, Olaf Klinke <[hidden email]> wrote:
>
> Dear cafe,
>
> prompted by a discussion with the author of blaze-markup [1] I realized a pattern and would like to know whether other haskellers have exploited this/find this useful:
>
> For every monoid m, the types Writer m () and m are isomorphic as types via tell and execWriter. Moreover, Writer m is a monad if and only if m is a monoid. For every monad t, the type t () is a monoid with
>   mempty = return ()
>   mappend = (>>).
> In the particular case of Writer m () and m, the isomorphism of Haskell types is in fact an isomorphism of monoids, that is, the functions tell and execWriter preserve the monoid operations.
>
> This enables us to use do-notation in building complicated values of any monoid type, e.g. Text or any other syntax. Instead of writing
>
> complicatedValue = component1 <>
>  component2 <>
>  modifier (component3 <> component4)
>
> one can write
>
> complicatedValue = execWriter $ do
>  component1
>  component2
>  modifier $ do
>    component3
>    component4
>
> Should such an idiom be encouraged/discouraged? How do you handle the construction of monoid values (especially text-like) with interspersed function applications (e.g. show, prettyprint)?
>
> Regards,
> Olaf
>
> [1] https://github.com/jaspervdj/blaze-markup/issues/36
> _______________________________________________
> Haskell-Cafe mailing list
> To (un)subscribe, modify options or view archives go to:
> http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
> Only members subscribed via the mailman list are allowed to post.


_______________________________________________
Haskell-Cafe mailing list
To (un)subscribe, modify options or view archives go to:
http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
Only members subscribed via the mailman list are allowed to post.



--
-Andrew Thaddeus Martin

_______________________________________________
Haskell-Cafe mailing list
To (un)subscribe, modify options or view archives go to:
http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
Only members subscribed via the mailman list are allowed to post.
Reply | Threaded
Open this post in threaded view
|

Re: do-notation for building monoid values

Brandon Allbery
The mconcat method is also how xmonad handles its ManageHooks, which are basically Endo Monoids.

On Thu, Mar 8, 2018 at 8:48 AM, Andrew Martin <[hidden email]> wrote:
I do the same thing that Merijn does. It works really well.

On Thu, Mar 8, 2018 at 8:08 AM, Merijn Verstraaten <[hidden email]> wrote:
I always just use mconcat and lists, so instead of:
> complicatedValue = execWriter $ do
>  component1
>  component2
>  modifier $ do
>    component3
>    component4

I write:

complicatedValue = mconcat
    [ component1
    , component2
    , modifier . mconcat $ [component3, component4]
    ]

Alternatively, if component3 and component4 are really long or lots of them linewrap those too:

complicatedValue = mconcat
    [ component1
    , component2
    , modifier . mconcat $
        [ component3
        , component4
        ]
    ]

Cheers,
Merijn

> On 8 Mar 2018, at 14:02, Olaf Klinke <[hidden email]> wrote:
>
> Dear cafe,
>
> prompted by a discussion with the author of blaze-markup [1] I realized a pattern and would like to know whether other haskellers have exploited this/find this useful:
>
> For every monoid m, the types Writer m () and m are isomorphic as types via tell and execWriter. Moreover, Writer m is a monad if and only if m is a monoid. For every monad t, the type t () is a monoid with
>   mempty = return ()
>   mappend = (>>).
> In the particular case of Writer m () and m, the isomorphism of Haskell types is in fact an isomorphism of monoids, that is, the functions tell and execWriter preserve the monoid operations.
>
> This enables us to use do-notation in building complicated values of any monoid type, e.g. Text or any other syntax. Instead of writing
>
> complicatedValue = component1 <>
>  component2 <>
>  modifier (component3 <> component4)
>
> one can write
>
> complicatedValue = execWriter $ do
>  component1
>  component2
>  modifier $ do
>    component3
>    component4
>
> Should such an idiom be encouraged/discouraged? How do you handle the construction of monoid values (especially text-like) with interspersed function applications (e.g. show, prettyprint)?
>
> Regards,
> Olaf
>
> [1] https://github.com/jaspervdj/blaze-markup/issues/36
> _______________________________________________
> Haskell-Cafe mailing list
> To (un)subscribe, modify options or view archives go to:
> http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
> Only members subscribed via the mailman list are allowed to post.


_______________________________________________
Haskell-Cafe mailing list
To (un)subscribe, modify options or view archives go to:
http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
Only members subscribed via the mailman list are allowed to post.



--
-Andrew Thaddeus Martin

_______________________________________________
Haskell-Cafe mailing list
To (un)subscribe, modify options or view archives go to:
http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
Only members subscribed via the mailman list are allowed to post.



--
brandon s allbery kf8nh                               sine nomine associates
[hidden email]                                  [hidden email]
unix, openafs, kerberos, infrastructure, xmonad        http://sinenomine.net

_______________________________________________
Haskell-Cafe mailing list
To (un)subscribe, modify options or view archives go to:
http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
Only members subscribed via the mailman list are allowed to post.
Reply | Threaded
Open this post in threaded view
|

Re: do-notation for building monoid values

Oliver Charles-3
Another mconcat user here. The only place it does fall down a bit is when you want something to be optional. In a monad we have `when`, but I don't know of any similar combinator for monoids. Of course, it's just `if x then y else mempty`, but I always end up defining a when-like function over and over again.

On Fri, Mar 9, 2018 at 12:53 AM Brandon Allbery <[hidden email]> wrote:
The mconcat method is also how xmonad handles its ManageHooks, which are basically Endo Monoids.

On Thu, Mar 8, 2018 at 8:48 AM, Andrew Martin <[hidden email]> wrote:
I do the same thing that Merijn does. It works really well.

On Thu, Mar 8, 2018 at 8:08 AM, Merijn Verstraaten <[hidden email]> wrote:
I always just use mconcat and lists, so instead of:
> complicatedValue = execWriter $ do
>  component1
>  component2
>  modifier $ do
>    component3
>    component4

I write:

complicatedValue = mconcat
    [ component1
    , component2
    , modifier . mconcat $ [component3, component4]
    ]

Alternatively, if component3 and component4 are really long or lots of them linewrap those too:

complicatedValue = mconcat
    [ component1
    , component2
    , modifier . mconcat $
        [ component3
        , component4
        ]
    ]

Cheers,
Merijn

> On 8 Mar 2018, at 14:02, Olaf Klinke <[hidden email]> wrote:
>
> Dear cafe,
>
> prompted by a discussion with the author of blaze-markup [1] I realized a pattern and would like to know whether other haskellers have exploited this/find this useful:
>
> For every monoid m, the types Writer m () and m are isomorphic as types via tell and execWriter. Moreover, Writer m is a monad if and only if m is a monoid. For every monad t, the type t () is a monoid with
>   mempty = return ()
>   mappend = (>>).
> In the particular case of Writer m () and m, the isomorphism of Haskell types is in fact an isomorphism of monoids, that is, the functions tell and execWriter preserve the monoid operations.
>
> This enables us to use do-notation in building complicated values of any monoid type, e.g. Text or any other syntax. Instead of writing
>
> complicatedValue = component1 <>
>  component2 <>
>  modifier (component3 <> component4)
>
> one can write
>
> complicatedValue = execWriter $ do
>  component1
>  component2
>  modifier $ do
>    component3
>    component4
>
> Should such an idiom be encouraged/discouraged? How do you handle the construction of monoid values (especially text-like) with interspersed function applications (e.g. show, prettyprint)?
>
> Regards,
> Olaf
>
> [1] https://github.com/jaspervdj/blaze-markup/issues/36
> _______________________________________________
> Haskell-Cafe mailing list
> To (un)subscribe, modify options or view archives go to:
> http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
> Only members subscribed via the mailman list are allowed to post.


_______________________________________________
Haskell-Cafe mailing list
To (un)subscribe, modify options or view archives go to:
http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
Only members subscribed via the mailman list are allowed to post.



--
-Andrew Thaddeus Martin

_______________________________________________
Haskell-Cafe mailing list
To (un)subscribe, modify options or view archives go to:
http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
Only members subscribed via the mailman list are allowed to post.



--
brandon s allbery kf8nh                               sine nomine associates
[hidden email]                                  [hidden email]
unix, openafs, kerberos, infrastructure, xmonad        http://sinenomine.net
_______________________________________________
Haskell-Cafe mailing list
To (un)subscribe, modify options or view archives go to:
http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
Only members subscribed via the mailman list are allowed to post.

_______________________________________________
Haskell-Cafe mailing list
To (un)subscribe, modify options or view archives go to:
http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
Only members subscribed via the mailman list are allowed to post.