Re: [Haskell-cafe] Best practices for Arrows?
Tom Ellis wrote: > Unfortunately my type doesn't have a Monad instance. If you could reveal the type, we could give more precise suggestions. > > In most cases when you expose an `Arrow` interface you can also > > expose a `Category`+`Applicative` interface, which is pretty much > > equivalent (except for a few extra laws): > > > > proc x -> do > > y1 <- a1 -< x > > y2 <- a2 -< x > > id -< x + y1 + y2^2 > > > > Is equivalent to: > > > > liftA3 (\x y1 y2 -> x + y1 + y2^2) id a1 a2 > > Yes, I can see how that would be useful. My question is: are you > talking about this Applicative instance: > > data MyArr a b = ... > > instance Arrow MyArr where > ... > > instance Functor (MyArr a) where > fmap f = (arr f <<<) > > instance Applicative (MyArr a) where > pure = arr . const > f <*> g = arr (uncurry ($)) <<< (f &&& g) Yes, that seems right. > I think I will be able to make my Arrow an ArrowLoop, but I haven't > checked. It's not that your type may have a useful or even sensible ArrowLoop notion, but if it does, then arrow notation is very useful. Also as Ross noted it gives you access to some additional convenience syntax, in particular if your type is an ArrowChoice. Those combinators are extremely awkward to use directly, but proc notation allows you to use regular if/case syntax. However, even then sometimes it can be beneficial to use composition of small self-contained arrow formulas. Greets, Ertugrul -- Not to be or to be and (not to be or to be and (not to be or to be and (not to be or to be and ... that is the list monad. signature.asc Description: PGP signature ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Best practices for Arrows?
On Sat, Jun 22, 2013 at 07:05:09PM +0100, Tom Ellis wrote: > On Sat, Jun 22, 2013 at 03:36:15PM +0200, Ertugrul Söylemez wrote: > > If the interface is not under your control, make yourself comfortable > > with the complete arrow syntax, most notably how it handles operators, > > combinators and the `(| banana bracket notation |)`. This is very > > valuable information. > > Interesting. I hadn't noticed the `(| banana bracket notation |)` on the > GHC Arrows page[1] before, but just saw it when I went back to check. The banana brackets can be handy when you have operations on your arrow type beyond the ones in Arrow and ArrowLoop. But beware that the types of the operations you can use with it will be changing in the next release of GHC. The change is the first one described on http://hackage.haskell.org/trac/ghc/wiki/ArrowNotation ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Best practices for Arrows?
Hi Ertugul. Thanks for taking the time to write me an in-depth reply! I have a few comments and a question. On Sat, Jun 22, 2013 at 03:36:15PM +0200, Ertugrul Söylemez wrote: > Tom Ellis wrote: > > > Are there any best-practices I should be aware of with Arrows? Or is > > it just a case of getting on with it? > > The best practice is probably to avoid them. If your type is a monad, > there is little reason to use the awkward arrow interface. Unfortunately my type doesn't have a Monad instance. > In most cases when you expose an `Arrow` interface you can also expose a > `Category`+`Applicative` interface, which is pretty much equivalent > (except for a few extra laws): > > proc x -> do > y1 <- a1 -< x > y2 <- a2 -< x > id -< x + y1 + y2^2 > > Is equivalent to: > > liftA3 (\x y1 y2 -> x + y1 + y2^2) id a1 a2 Yes, I can see how that would be useful. My question is: are you talking about this Applicative instance: data MyArr a b = ... instance Arrow MyArr where ... instance Functor (MyArr a) where fmap f = (arr f <<<) instance Applicative (MyArr a) where pure = arr . const f <*> g = arr (uncurry ($)) <<< (f &&& g) > If the interface is not under your control, make yourself comfortable > with the complete arrow syntax, most notably how it handles operators, > combinators and the `(| banana bracket notation |)`. This is very > valuable information. Interesting. I hadn't noticed the `(| banana bracket notation |)` on the GHC Arrows page[1] before, but just saw it when I went back to check. > Try to separate individual computations as much as possible and compose > using `(.)` (or `(<<<)`/`(>>>)` if you prefer). This makes your code > much more readable: Yes, agreed. I'm a strong proponent of using (.) for functions and (<=<) when dealing with Monads. > There is one case where the arrow notation is really indispensable: > value recursion via `ArrowLoop`: [...] I think I will be able to make my Arrow an ArrowLoop, but I haven't checked. Thanks again, Tom [1] http://www.haskell.org/ghc/docs/latest/html/users_guide/arrow-notation.html ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Best practices for Arrows?
Tom Ellis wrote: > Are there any best-practices I should be aware of with Arrows? Or is > it just a case of getting on with it? The best practice is probably to avoid them. If your type is a monad, there is little reason to use the awkward arrow interface. In some cases the arrow interface can improve the asymptotic performance though, for example in the case of `Auto` (which is actually a monad, but the monadic interface introduces a space leak). In most cases when you expose an `Arrow` interface you can also expose a `Category`+`Applicative` interface, which is pretty much equivalent (except for a few extra laws): proc x -> do y1 <- a1 -< x y2 <- a2 -< x id -< x + y1 + y2^2 Is equivalent to: liftA3 (\x y1 y2 -> x + y1 + y2^2) id a1 a2 All arrows give rise to a [Profunctor] instance, so instead of `arr` you can use `lmap` and `rmap`/`fmap`: arr f . c = fmap f c c . arr f = lmap f c If the interface is not under your control, make yourself comfortable with the complete arrow syntax, most notably how it handles operators, combinators and the `(| banana bracket notation |)`. This is very valuable information. Try to separate individual computations as much as possible and compose using `(.)` (or `(<<<)`/`(>>>)` if you prefer). This makes your code much more readable: c = a . b . c where a = {- ... -} b = {- ... -} c = {- ... -} There is one case where the arrow notation is really indispensable: value recursion via `ArrowLoop`: proc _ -> do rec v <- integral -< x + 1 x <- integral -< v id -< (x, v) Here the position x is the integral of the velocity, which is itself the integral of the position + 1. This is awkward to express in terms of `loop`, so arrow notation is really a big helper here. [Profunctor]: http://hackage.haskell.org/package/profunctors Greets, Ertugrul -- Not to be or to be and (not to be or to be and (not to be or to be and (not to be or to be and ... that is the list monad. signature.asc Description: PGP signature ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe