Arrow Classes

Joe English jenglish@flightlab.com
Sat, 28 Jun 2003 09:00:55 -0700


Ashley Yakeley wrote:
> Wolfgang Jeltsch wrote:
>
> > This brings me to another point. One year ago we had a discussion on The
> > Haskell Mailing List concerning arrows. (The subject of the mails was just
> > "arrows".) The point was that it seemed strange to me that first and second
> > are included in the basic arrow class Arrow while left and right have their
> > extra class ArrowChoice. Not only that it seemed strange to me but it made
> > impossible to make Parser baseMonad an instance of Arrow. Parser baseMonad
> > has nice implementations of pure and (>>>) but none of first or second.
>
> I agree. My own Arrow module hierarchy looks more or less like this:
>
>   class Compositor comp where [...]
>   class (Compositor arrow) => Arrow arrow where [...]
>   class (Arrow arrow) => ProductArrow arrow where [...]
>   class (Arrow arrow) => CoproductArrow arrow where [...]
>   class (ProductArrow arrow,CoproductArrow arrow) => FullArrow arrow
>   instance (ProductArrow arrow,CoproductArrow arrow) => FullArrow arrow
>   class (Arrow arrow) => ArrowFix arrow where [...]
>   class (FullArrow arrow) => ApplyArrow arrow where [...]


On that topic, see below for what mine looks like
(from HXML, <URL: http://www.flightlab.com/~joe/hxml/ >).

I started off with Hughes' conventions, but for some
reason could never remember the difference between &&& and ***,
or between ||| and +++.  I found &&&, >&<, |||, >|< to have
better mnemonic value.  This also frees up +++ for ArrowPlus,
which -- in HXML applications -- is frequently used and should
thus be easy to type.

When using the ArrowChoice operators, I kept tripping over all
the 'Either' coproduct types, so added some syntactic sugar
(borrowed from HaXML):

data Choice a = a :> a
class (Arrow a) => ArrowChoice a where
	[ ... ]
	( ?>)	:: (b -> Bool) -> Choice (a b c) -> a b c
	(>?>)	:: a b Bool    -> Choice (a b c) -> a b c

I found "p ?> f :> g" much more pleasant to use.

(I also like the idea of splitting the product operators out of
the base Arrow class -- will consider doing that in my library).

--

infixr 5 +++
infixr 3 >&<, &&&
infixr 2 >|<, |||, ?>, >?>, :>
infixl 1 >>>

class Arrow a where
	arr	:: (b -> c) -> a b c
	(>>>)	:: a b c -> a c d -> a b d
	apfst	:: a b c -> a (b,x) (c,x)
	apsnd	:: a b c -> a (x,b) (x,c)
	(>&<)	:: a b c -> a d e -> a (b,d) (c,e)
	(&&&)	:: a b c -> a b d -> a b (c,d)
	liftA2	:: (b -> c -> d) -> a e b -> a e c -> a e d
	aConst	:: c -> a b c
	idArrow	:: a b b
	-- Minimal implementation: arr, >>>,  apfst or >&<

data Choice a = a :> a
class (Arrow a) => ArrowChoice a where
	apl	:: a b c -> a (Either b d) (Either c d)
	apr	:: a b c -> a (Either d b) (Either d c)
	(>|<)	:: a b c -> a d e -> a (Either b d) (Either c e)
	(|||)	:: a b c -> a d c -> a (Either b d) c
	( ?>)	:: (b -> Bool) -> Choice (a b c) -> a b c
	(>?>)	:: a b Bool    -> Choice (a b c) -> a b c
	-- Minimal implementation: >|< or apl

class (Arrow a) => ArrowApply a where
	app :: a (a b c,b) c

class (Arrow a) => ArrowZero a where
	aZero  :: a b c
	aMaybe :: a (Maybe c) c
	aGuard :: (b -> Bool) -> a b b

class (Arrow a) => ArrowPlus a where
	(+++) :: a b c -> a b c -> a b c



--Joe English

  jenglish@flightlab.com