<div dir="ltr"><div><span style="font-size:12.8px">>The changelog for 0.8.0.0 [1] advertises: Make `MarkupM` finally adhere</span><br style="font-size:12.8px"><span style="font-size:12.8px">>to the Monad laws</span><div><span style="font-size:12.8px">Nice. I searched the issue tracker on GitHub but ought to have just looked at the changelog.</span></div></div><div><br></div>><span style="font-size:12.8px">Please, if you think blaze-markup violates the Monad laws, then report a</span><br style="font-size:12.8px"><span style="font-size:12.8px">>counterexample so it will get fixed.</span><br style="font-size:12.8px"><div>Not really. Hence the caveat. But just to clarify, my thinking* was this:</div><div><br></div><div>return a >>= f </div><div>= Empty a >>= f</div><div>= Append (Empty a) (f (markupValue (Empty a)))</div><div>= Append (Empty a) (f a)</div><div>≠ f a</div><div><br></div><div><div><b>BUT </b>you can only observe this by importing Blaze.Text.Internal and pattern matching on MarkupM. Using renderMarkup you can't observe it. So long as a user can't observe the difference (or is at least discouraged by a scary-looking .Internal suffix), it's just an implementation detail that the data constructors don't exactly match. </div></div><div><br></div><div>Cheers,</div><div>Mike</div><div><br></div><div><div>*: using = and ≠ to mean "exactly the same as", like a derived Eq instance, rather than e.g. <a href="https://github.com/jaspervdj/blaze-markup/blob/master/tests/Text/Blaze/Tests.hs#L179">https://github.com/jaspervdj/blaze-markup/blob/master/tests/Text/Blaze/Tests.hs#L179</a> which compares different Markup renderings.</div></div><div><br></div></div><div class="gmail_extra"><br><div class="gmail_quote">On Fri, Oct 27, 2017 at 1:53 AM, Oleg Grenrus <span dir="ltr"><<a href="mailto:oleg.grenrus@iki.fi" target="_blank">oleg.grenrus@iki.fi</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Please, if you think blaze-markup violates the Monad laws, then report a<br>
counterexample so it will get fixed.<br>
<br>
The changelog for 0.8.0.0 [1] advertises: Make `MarkupM` finally adhere<br>
to the Monad laws<br>
<br>
<a href="http://hackage.haskell.org/package/blaze-markup-0.8.0.0/changelog" rel="noreferrer" target="_blank">http://hackage.haskell.org/<wbr>package/blaze-markup-0.8.0.0/<wbr>changelog</a><br>
<br>
Cheers, Oleg.<br>
<span class=""><br>
<br>
On 26.10.2017 16:54, Mike Ledger wrote:<br>
> >Do you mind explaining the invalid monad instance of Lucid and how it<br>
> would impact a library user?<br>
> To my knowledge lucid uses a monad instance that follow the monad laws<br>
> (what I meant by "valid") fine.<br>
><br>
> It's blaze that's (somewhat) infamous for having an invalid monad<br>
> instance. It used to be the case that (>>=) in blaze called 'error' --<br>
> the Monad instance was to just use (>>) = mappend. Looking now, the<br>
> implementation has changed and my knowledge was out-of-date. I think<br>
> it still violates the monad laws, but I don't know if as a user of<br>
> blaze you'd ever be able to actually observe this, if that makes any<br>
> sense.<br>
><br>
> For some fun discussions on this see:<br>
> -<br>
> <a href="https://stackoverflow.com/questions/6399648/what-happens-to-you-if-you-break-the-monad-laws" rel="noreferrer" target="_blank">https://stackoverflow.com/<wbr>questions/6399648/what-<wbr>happens-to-you-if-you-break-<wbr>the-monad-laws</a><br>
> -<br>
> <a href="https://www.reddit.com/r/haskell/comments/16iakr/what_happens_when_a_monad_violates_monadic_laws/" rel="noreferrer" target="_blank">https://www.reddit.com/r/<wbr>haskell/comments/16iakr/what_<wbr>happens_when_a_monad_violates_<wbr>monadic_laws/</a><br>
><br>
</span>> How invalid monads /can/ impact users is better explored in the SO<br>
<span class="im HOEnZb">> question.<br>
><br>
> >Also, I'm assuming one shouldn't call the `compile` function each<br>
> time a page needs to be rendered, right? Should one put the results of<br>
> the `compile` function in a top-level Map and use those to get the<br>
> speed gains?<br>
> The idea is to only compile a template once, ever. If you need to<br>
> compile a template every time a page is rendered (though I can't<br>
> actually think of a case where you would), you should probably just<br>
> skip the middle-man, and use lucid (or blaze). It's not horribly slow,<br>
> but you'd miss out on the benefits of nice-html by doing this.<br>
><br>
> Cheers<br>
><br>
> On Thu, Oct 26, 2017 at 11:51 PM, Saurabh Nanda<br>
</span><span class="im HOEnZb">> <<a href="mailto:saurabhnanda@gmail.com">saurabhnanda@gmail.com</a> <mailto:<a href="mailto:saurabhnanda@gmail.com">saurabhnanda@gmail.com</a><wbr>>> wrote:<br>
><br>
>     Thank you for putting comparisons and benchmarks, upfront.<br>
><br>
>     Do you mind explaining the invalid monad instance of Lucid and how<br>
>     it would impact a library user?<br>
><br>
>     Also, I'm assuming one shouldn't call the `compile` function each<br>
>     time a page needs to be rendered, right? Should one put the<br>
>     results of the `compile` function in a top-level Map and use those<br>
>     to get the speed gains?<br>
><br>
>     Side comment, the use of `dynamic` makes it look similar to reflex<br>
>     `dyn*` API.<br>
><br>
>     -- Saurabh.<br>
><br>
>     On Thu, Oct 26, 2017 at 4:15 PM, Mike Ledger<br>
</span><div class="HOEnZb"><div class="h5">>     <<a href="mailto:eleventynine@gmail.com">eleventynine@gmail.com</a> <mailto:<a href="mailto:eleventynine@gmail.com">eleventynine@gmail.com</a><wbr>>> wrote:<br>
><br>
>         Hi Haskell-Cafe,<br>
><br>
>         I've been working on and off on a HTML templating library that<br>
>         is slightly novel for a few months. <br>
><br>
>         Here's the good parts:<br>
>         * it's faster than lucid and blaze<br>
>         * it has a valid monad instance<br>
>         * it has another valid monad instance, that is slightly different!<br>
>         * it paramaterises templates by the data they require<br>
>         * the HTML5 combinators don't rely on any highly<br>
>         overloaded/overlapping typeclasses; type errors in nice-html<br>
>         templates tend to be nice monomorphic type mismatches<br>
><br>
>         To achieve this, it has a distinct compilation phase (at<br>
>         runtime) for templates. This means the actual rendering<br>
>         function does very little beyond concatenate Text and escape<br>
>         dynamic input. It also severely restricts usage to the<br>
>         built-in combinators available -- at least, for dynamic data<br>
>         -- and can make writing a nice-html template difficult, though<br>
>         littering _ throughout type signatures helps.<br>
><br>
>         Check it out!<br>
><br>
>         Benchmark results, a README, and an example:<br>
>         <a href="https://github.com/TransportEngineering/nice-html" rel="noreferrer" target="_blank">https://github.com/<wbr>TransportEngineering/nice-html</a><br>
>         <<a href="https://github.com/TransportEngineering/nice-html" rel="noreferrer" target="_blank">https://github.com/<wbr>TransportEngineering/nice-html</a><wbr>><br>
>         Hackage: <a href="https://hackage.haskell.org/package/nice-html" rel="noreferrer" target="_blank">https://hackage.haskell.org/<wbr>package/nice-html</a><br>
>         <<a href="https://hackage.haskell.org/package/nice-html" rel="noreferrer" target="_blank">https://hackage.haskell.org/<wbr>package/nice-html</a>><br>
><br>
>         The only thing on the roadmap right now is to have some nice<br>
>         :-) way to assign JavaScript event handlers to Markup. This is<br>
>         something that I really appreciate when using React.js, so my<br>
>         eventual aim is for nice-html to be like a (more) server-side<br>
>         version of React. Right now, you can keep track of element ids<br>
>         with `Text.Html.Writer.note`, but it's neither a very good nor<br>
>         very useful interface.<br>
><br>
>         Cheers,<br>
>         Mike<br>
><br>
>         ______________________________<wbr>_________________<br>
>         Haskell-Cafe mailing list<br>
>         To (un)subscribe, modify options or view archives go to:<br>
>         <a href="http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe" rel="noreferrer" target="_blank">http://mail.haskell.org/cgi-<wbr>bin/mailman/listinfo/haskell-<wbr>cafe</a><br>
>         <<a href="http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe" rel="noreferrer" target="_blank">http://mail.haskell.org/cgi-<wbr>bin/mailman/listinfo/haskell-<wbr>cafe</a>><br>
>         Only members subscribed via the mailman list are allowed to post.<br>
><br>
><br>
><br>
><br>
>     --<br>
>     <a href="http://www.saurabhnanda.com" rel="noreferrer" target="_blank">http://www.saurabhnanda.com</a><br>
><br>
><br>
><br>
><br>
> ______________________________<wbr>_________________<br>
> Haskell-Cafe mailing list<br>
> To (un)subscribe, modify options or view archives go to:<br>
> <a href="http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe" rel="noreferrer" target="_blank">http://mail.haskell.org/cgi-<wbr>bin/mailman/listinfo/haskell-<wbr>cafe</a><br>
> Only members subscribed via the mailman list are allowed to post.<br>
<br>
<br>
</div></div></blockquote></div><br></div>