Who is afraid of arrows, was Re: [Haskell-cafe] ANNOUNCE: Haskell
XML Toolbox Version 9.0.0
gcross at phys.washington.edu
Tue Oct 12 16:44:05 EDT 2010
On 10/12/10 6:29 AM, Sebastiaan Visser wrote:
> I use arrows (especially list arrows) in a lot of my projects and find them (after some training) easier to work with than monands. Code that I write point-free using arrows generally contains fewer bugs than code I write in monadic style.
So what it is that you like is the point-free style rather than the use
of arrows. There is nothing stopping you from using point-free style
with monads, and I personally prefer to do so when I can. So to repeat
this again, I am not arguing against point-free style, I am arguing
against basing libraries on arrows instead of monads unless one
specifically needs the more general structure of the arrows because
otherwise it makes life less convenient for the user as (among other
reasons) it introduces extra syntax and prevents use of standard monad
combinators and libraries.
> I think it is unfair to say that arrows add complexity over monads. This statement can only be true to people who actually know monads and do not know arrows. This has more to do with the direction of one's knowledge than the 'complexity' (whatever this means) of a programming abstraction.
I can assure you that I have spent a lot of time looking at arrows and
even once wrote and used instance of Arrow myself in a situation where a
monad would not have been appropriate. To be specific: the additional
complexity comes from the fact that additional notation is needed to
accomplish the same goal, and from the fact that standard monad
combinators and libraries cannot be used. This isn't simply a matter of
being unfamiliar with arrows.
> Don't see arrows a less restricted monads, see them as a generalization of functions, than it will all make sense. Use them in situations that need generalization of functions, not in cases that require the power of monads.
I am not sure what you are getting at with this, because your
description contradicts my usual notion of when one uses monads and
arrows --- namely, when one is working with a structure that fits one or
the other of the two patterns and one wants to leverage special
libraries and/or syntax.
>>> Arrows are a generalisation of functions, so if you know all about working
>>> with functions you know (almost) all about working with arrows.
>>> When generalizing a pure algorithm, something like "f3 . f2 . f1",
>>> or in Unix pipe style "f1>>> f2>>> f3", you don't have to rewrite
>>> the code, you just generalize function composition.
>> Yes, but the>=> operator lets you do the same thing with monads, and in fact I use it all the time to do point-free programming with monads, so this isn't at all an advantage that arrows have over monads.
> I'd rather use (.) for composition of expressions than (<=<) and I'd rather use the 'id' for identity than return. Writing my arrow computations point-free as if they were functions feels far less clumsy and a far more readable than monadic style.
Fair enough, but again, in exchange for these two operators you lose
monadic combinators and libraries and introduce additional syntax.
>>> When constructing code, it is of course sometimes simpler to start with a
>>> point wise version and then refactor and rewrite it into a more compact point
>>> free version. The problem with arrows seems, that the arrow style forces to
>>> start with the point free style. And that may be the main hurdle in mind.
>> No, that is not at all the problem with arrows. The problem with arrows is that they are more restrictive than monads in two respects. First, unlike monads, in general they do not let you perform an arbitrary action in response to an input. Second, they place restrictions on how you define the input arguments of the arrow because you can't feed the output of one arrow into to input of the next unless said input is captured in the arrows type.
> This restriction, though not always, can be very useful. This restriction allows you to do full inspection of the arrow expression. This inspection can in some cases be used to serialize an arrow computation of statically optimize it to a more efficient form.
I agree completely! This is *exactly* the kind of time when it is
appropriate to use an arrow. The choice of whether to use an arrow or a
monad should be based on the structure of the underlying system, with
the latter to be preferred unless there is a good reason to choose the
> When you don't need the power of Monads (or ArrowApply) why use a formalism that does provide this power? That will only make it harder to reason about your program, which isn't quite the Haskell way.
Because, again, it makes the life of the user of your library easier ---
for example, when they decide to use it in a way that is perfectly
legitimate but is not something you had thought of in advance.
Put another way, why should one place an arbitrary restriction on the
user when there is nothing gained by it?
> I've worked with HXT quite a lot and find XML arrows very convenient.
More information about the Haskell-Cafe