
I propose to refactor the Arrow class, so that GHC's arrow notation can be a bit more general. (The module Control.Arrow itself would remain standard Haskell.) Please comment by 12th August. In detail, the proposal is to change the Arrow class from class Category a => Arrow a where arr :: (b -> c) -> a b c first :: a b c -> a (b,d) (c,d) -- various functions made methods to allow efficient specializations by introducing a new class -- | A binary type constructor that is contravariant in its first argument, -- that is, -- -- * @'premap' id a = a@ -- -- * @'premap' (f . g) a = 'premap' g ('premap' f a)@ -- class PreArrow a where premap :: (b -> b') -> a b' c -> a b c with instances instance PreArrow (->) where premap f g = g . f instance PreArrow (Kleisli m) where premap f (Kleisli g) = Kleisli (g . f) and redefining the Arrow class as class (Category a, PreArrow a) => Arrow a where arr :: (b -> c) -> a b c arr f = premap f id first :: a b c -> a (b,d) (c,d) -- rest unchanged The proposed PreArrow class has more instances than Arrow, in particular composing a PreArrow with a Functor yields another PreArrow. The principal client for the new class would be the arrow notation, as implemented in GHC. With this class, there would be a simple rule for determining which instances are needed, based on the keywords used: * all commands ("proc" and operator arguments) need PreArrow * "do" needs Arrow * "rec" needs ArrowLoop * "case" or "if" need ArrowChoice One might object that the second argument of the PreArrow class is superfluous, and this is just a complicated Contravariant class. That is true, and in semantic terms a covariant functor would be sufficient, but Haskell's type system makes it impossible to have commonality between a Contravariant class of unary type constructors and the Arrow class used by arrow notation.