# [Haskell-cafe] Plain lambda inside banana brackets in the arrow notation

Ross Paterson ross at soi.city.ac.uk
Thu Jul 12 15:47:57 CEST 2012

```On Thu, Jul 05, 2012 at 10:55:07PM +0100, Tsuyoshi Ito wrote:
> In a program, I have an arrow MyArr and a combinator called repeat of
> the following type:
>
>     repeat :: Int -> (Int -> MyArr e a) -> MyArr e a
>
> My problem is that the code becomes messy when I use this combinator
> inside the arrow notation, and I am looking for a way to write the
> code in a more readable way.
> [...]
> It does not seem possible to use banana brackets here because the type
> of the subcomputation does not meet the requirements stated in
>
> How can I use combinators like repeat, which takes a plain function as
> an argument, in the arrow notation in a more readable way?  Or am I
> trying to do an impossible thing?

Unfortunately the arrow notation doesn't support this.  There's no
semantic reason why it wouldn't work with arguments of the form

f (a (...(e,t1), ... tn) t)

for any functor f, or even

g (...(e,t1), ... tn)

for any contravariant functor g.  The limitation is due to Haskell's
structural matching of types.  Though one possibility that might get
us most of the way there would be to refactor the Arrow class as

class PreArrow a where
premap :: (b -> b') -> a b' c -> a b c

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)

instance PreArrow (->) where
premap f g = g . f

instance PreArrow (Kleisli m) where
premap f (Kleisli g) = Kleisli (g . f)

instance (PreArrow a, Functor f) => PreArrow (StaticArrow f a) where
premap f (StaticArrow g) = StaticArrow (fmap (premap f) g)

The PreArrow class would be sufficient for the low-level translation
(i.e. excluding if, case and do).  You'd need to fiddle with newtypes
to use it in your example, though.

```