<div dir="ltr"><div class="gmail_quote"><div dir="ltr">On Fri, Sep 29, 2017 at 2:56 AM Viktor Dukhovni <<a href="mailto:ietf-dane@dukhovni.org" target="_blank">ietf-dane@dukhovni.org</a>> wrote:</div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
<br>
Can you explain that qualification?<br></blockquote><div><br></div><div>I mean that you don't need to use (>>=) on the IO inside the RowParser.</div><div><br></div><div>The composition of two Applicatives is also an Applicative. If you upgrade one to Monad this is no longer true. Since you're only using (>>)</div><div>(which is really an Applicative operation in disguise), we don't need to worry here.</div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
Indeed this works, and looks more clear than some new unfamiliar operator.<br>
This seems to have no measurable run-time cost. Is it reasonable to expect<br>
that under the covers no objects boxed as (Compose _) are ever created, and<br>
that Compose here is just compile-time syntactic sugar for applying (*>) at<br>
the desired layer, so that:<br>
<br>
getCompose $ Compose (Foo Bar a)<br>
*> Compose (Foo Bar b)<br>
*> Compose (Foo Bar c)<br>
...<br>
*> Compose (Foo Bar z)<br>
<br>
just compiles down to Foo (Bar a *> Bar b *> Bar c *> ... *> Bar z)?<br>
Where, in my case, Foo is "RowParser" and Bar is IO?<br></blockquote><div><br></div><div>If we tried to write a typeclass instance for "composition of applicatives", it might look something like this:</div><div><br></div><div>instance (Applicative f, Applicative g) => forall a. Applicative (f (g a)) where</div><div> ...</div><div><br></div><div>But we're not allowed to write such an instance. To get around this, a newtype is created:</div><div><br></div><div>newtype Compose f g a = Compose { getCompose :: f (g a) }</div><div><br></div><div>and a valid instance can be written:</div><div><br></div><div><div>instance (Applicative f, Applicative g) => Applicative (Compose f g) where</div></div><div> pure = Compose . pure . pure</div><div> a <*> b = Compose $ liftA2 (<*>) a b</div><div><br></div><div>You are correct in assuming it has no runtime cost- at runtime the `f (g a)` is passed around as normal, but at compile</div><div>time, `Compose f g a` is considered distinct to `f (g a)`.</div><div><br></div><div>Due to this typeclass instance,</div><div><br></div><div>getCompose $</div><div>Compose a *></div><div>Compose b *></div><div>Compose c</div><div><br></div><div>is equivalent to</div><div><br></div><div>liftA2 (*>) (liftA2 (*>) a b) c</div><div><br></div><div><br></div><div><br></div><div><br></div></div></div>