12
votes

I'm still getting to grips with defining and using Arrows in Haskell. While defining new arrows, it is much easier for me to think in terms of *** or &&& rather than first and second, as most of the time I want special processing for when two arrows are combined.

However the Arrow class does not allow defining the arrow in terms of arr and *** or &&&, and requires a definition of first to be included. This means that I am forced to write code like the following -

instance Arrow X where
  arr f = ...
  f (***) g = ...
  first f = f *** arr id

It seems to me that there would have been no harm in including a default definition of 'first' as well in the Control.Arrow module. That would have allowed us to choose between defining either first or ***.

Is there a good reason why a default definition of first was not included in the Arrow class? The only reason that I can think of is that the user may leave out the definition of first and *** both and then you would have circular definitions, but is that the only reason?

2
I doubt the possibility of a circular definition is the reason, because that exact situation exists in other type classes; for instance, (==) and (/=) in Eq.C. A. McCann

2 Answers

5
votes

Data.Monoid has a similar missing alternative minimal-complete-definition: mconcat. Like with Arrow, it is missing this alternative out of performance reasons. mappend a b = mconcat[a,b] is inefficient because of the pattern-matching in mconcat.

With Arrows, the inefficiency is less obvious but more brutal: Think about not being able to optimize arr id away:

Using CleisliArrow as example Arrow, it is like this:

first f (x,y) = do
    x' <- f x
    return (x',y)

And it would be:

first f (x,y) = do
    x' <- f x
    y' <- arr id y
    return (x',y')

The arr function cannot pattern-match the id function and has therefore to introduce additional overhead to wrap that function.

4
votes

I actually believe it's the circularity that stopped someone from writing the default methods. But as @camccann pointed out, this should stop anyone. Suggest a change!