Re: [Haskell-cafe] Best practices for Arrows?

2013-06-23 Thread Ertugrul Söylemez
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?

2013-06-22 Thread Ross Paterson
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?

2013-06-22 Thread Tom Ellis
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?

2013-06-22 Thread Ertugrul Söylemez
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