proposal #2517: remove 'pure' method from Arrow class

The Arrow class as originally defined by John Hughes had methods arr, >>> and first. (>>> has since been moved by #1773 to the Category class.) When writing the "Fun of Programming" paper, I added pure as a synonym for arr, because Richard Bird preferred it. However this name hasn't caught on, and now it clashes with a method in the Applicative class, so I propose to remove it. The usual practice would be to deprecate the name in one release and remove it in the following one, but I propose to remove it in one step because * no-one seems to be using this name, and * backward compatibility has been broken anyway by the Category split (#1773). The only people who will be bitten by the change are those who import Control.Arrow hiding pure, and they wouldn't be warned by deprecation.

Ross Paterson wrote:
The Arrow class as originally defined by John Hughes had methods arr, >>> and first. (>>> has since been moved by #1773 to the Category class.) When writing the "Fun of Programming" paper, I added pure as a synonym for arr, because Richard Bird preferred it. However this name hasn't caught on, and now it clashes with a method in the Applicative class, so I propose to remove it.
I agree with deleting 'pure' from there. Now assuming that, I'm wondering... It looks like all Arrows are Applicative; is that a useful observation? (and then even further off topic, but it's still important); As follows: <*> :: (Applicative f) => f (a -> b) -> f a -> f b so <*> :: (Arrow arr) => arr x (a -> b) -> arr x a -> arr x b fmap :: (Arrow arr) => (a -> b) -> arr x a -> arr x b pure :: (Applicative f) => a -> f a pure :: (Arrow arr) => a -> arr x a Interesting, it looks a bit similar to 'Reader x', is that okay? instance (Arrow arr) => Applicative (arr x) where pure a = arr (const a) fmap f a = a >>> arr f f <*> a = fmap (uncurry ($)) (f &&& a) But I seem to recall arrConst indeed being of significance, for example. And the above definition of <*> preserves the ordering of f and a; for example, the effect-order-reversing Applicative-transformer could accurately be applied here. So I think it's nontrivially useful. Not all Applicatives are Arrows though! ArrowPlus, of course, corresponds with Alternative; the full types of the appending operation's arguments must be identical in all cases. instance (Arrow arr) => Alternative (arr x) where empty = zeroArrow; (<|>) = (<+>) and thenceforth with Monoid instance (Arrow arr) => Alternative (arr a b) where mempty = zeroArrow; mappend = (<+>) . It makes me wonder what is the point of ArrowPlus, MonadPlus, Alternative... when we have Monoid. But are they usable in all the same situations? It seems some places that use f :: (MonadPlus f) => ... would indeed need to require the polymorphic (invented syntax) f :: (forall a. Monoid (f a)) => ... not just for some particular 'a' f :: (Monoid (f a)) => ... Why does that make sense? Should it? Did I get confused somehow? -Isaac

On Fri, Aug 15, 2008 at 9:58 AM, Isaac Dupree
It looks like all Arrows are Applicative; is that a useful observation?
The WrappedArrow type in Control.Applicative creates an applicative functor from any arrow. The paper "Idioms are oblivious, arrows are meticulous, monads are promiscuous" by Lindley, Wadler, and Yallop has a good explanation of the relationship between arrows and applicative functors. http://homepages.inf.ed.ac.uk/wadler/papers/arrows-and-idioms/arrows-and-idi... http://lambda-the-ultimate.org/node/2799
ArrowPlus, of course, corresponds with Alternative; the full types of the appending operation's arguments must be identical in all cases. instance (Arrow arr) => Alternative (arr x) where empty = zeroArrow; (<|>) = (<+>) and thenceforth with Monoid instance (Arrow arr) => Alternative (arr a b) where mempty = zeroArrow; mappend = (<+>) . It makes me wonder what is the point of ArrowPlus, MonadPlus, Alternative... when we have Monoid.
But are they usable in all the same situations? It seems some places that use f :: (MonadPlus f) => ... would indeed need to require the polymorphic (invented syntax) f :: (forall a. Monoid (f a)) => ... not just for some particular 'a' f :: (Monoid (f a)) => ...
Why does that make sense? Should it? Did I get confused somehow?
MonadPlus is more restrictive than Monoid in (at least) two ways.
First, the instances of MonadPlus have kind * -> *, whereas the
instances of Monoid have kind *. With Monoid, you can easily constrain
a type constructor's parameter, e.g.:
instance (Foo a) => Monoid (Bar a) where ...
With MonadPlus, this is not possible.
Second, instances of MonadPlus must obey additional laws governing
their relationship to the Monad operations. In addition to mplus and
mzero forming a monoid, mzero must[1] be a left zero for (>>=),
mzero >>= f = mzero
and (>>=) must[2] left-distribute over mplus,
mplus a b >>= f = mplus (a >>= f) (b >>= f)
The differences between Monoid, ArrowPlus, and Alternative are
similar, although I don't recall seeing laws stated for Alternative.
[1] Has anyone examined whether it's possible to violate this law
while still satisfying the monad and monoid laws?
[2] Not everyone agrees with this law. In fact, the instance for Maybe
in Control.Monad doesn't satisfy it. Generally, any monad which uses
mplus for exception handling instead of non-determinism will not
satisfy this law.
--
Dave Menendez

On Fri, Aug 15, 2008 at 8:44 AM, Ross Paterson
The Arrow class as originally defined by John Hughes had methods arr, >>> and first. (>>> has since been moved by #1773 to the Category class.) When writing the "Fun of Programming" paper, I added pure as a synonym for arr, because Richard Bird preferred it. However this name hasn't caught on, and now it clashes with a method in the Applicative class, so I propose to remove it.
I agree.
Personally, I prefer 'pure' to 'arr' for arrows, and I wish we could
have called the operation in Applicative something different, but it's
too late for that.
--
Dave Menendez

On Sat, Aug 16, 2008 at 01:06:29AM -0700, Ashley Yakeley wrote:
David Menendez wrote:
Personally, I prefer 'pure' to 'arr' for arrows, and I wish we could have called the operation in Applicative something different, but it's too late for that.
Hopefully one day the Applicative function will be called "return".
Certainly Functor (fmap) PreMonad (return) Applicative ((<*>)) Monad ((>>=)/join) would be the rational hierarchy, but don't hold your breath.
participants (4)
-
Ashley Yakeley
-
David Menendez
-
Isaac Dupree
-
Ross Paterson