Arrows are a generalization of monads introduced by John Hughes. For more details, see

“Generalising Monads to Arrows”, John Hughes, in

*Science of Computer Programming*37, pp67–111, May 2000.“A New Notation for Arrows”, Ross Paterson, in

*ICFP*, Sep 2001.“Arrows and Computation”, Ross Paterson, in

*The Fun of Programming*, Palgrave, 2003.

The extension adds a new kind of expression for defining arrows,
of the form `proc pat -> cmd`,
where `proc` is a new keyword.
The variables of the pattern are bound in the body of the
`proc`-expression,
which is a new sort of thing called a *command*.
The syntax of commands is as follows:

cmd ::= exp1 -< exp2 | exp1 -<< exp2 | do { cstmt1 .. cstmtn ; cmd } | let decls in cmd | if exp then cmd1 else cmd2 | case exp of { calts } | cmd1 qop cmd2 | (| aexp cmd1 .. cmdn |) | \ pat1 .. patn -> cmd | cmd aexp | ( cmd ) cstmt ::= let decls | pat <- cmd | rec { cstmt1 .. cstmtn } | cmd |

A simple example of the new notation is the expression

proc x -> f -< x+1 |

arr (\ x -> x+1) >>> f |

proc x -> f x -<< x+1 |

arr (\ x -> (f, x+1)) >>> app |

Another form of command is a form of `do`-notation.
For example, you can write

proc x -> do y <- f -< x+1 g -< 2*y let z = x+y t <- h -< x*z returnA -< t+z |

arr (\ x -> (x, x)) >>> first (arr (\ x -> x+1) >>> f) >>> arr (\ (y, x) -> (y, (x, y))) >>> first (arr (\ y -> 2*y) >>> g) >>> arr snd >>> arr (\ (x, y) -> let z = x+y in ((x, z), z)) >>> first (arr (\ (x, z) -> x*z) >>> h) >>> arr (\ (t, z) -> t+z) >>> returnA |

arr (\ x -> (x+1, x)) >>> first f >>> arr (\ (y, x) -> (2*y, (x, y))) >>> first g >>> arr (\ (_, (x, y)) -> let z = x+y in (x*z, z)) >>> first h >>> arr (\ (t, z) -> t+z) |

Note that although the above translation suggests that
`let`-bound variables like `z` must be
monomorphic, the actual translation produces Core,
so polymorphic variables are allowed.

It's also possible to have mutually recursive bindings,
using the new `rec` keyword, as in the following example:

counter :: ArrowCircuit a => a Bool Int counter = proc reset -> do rec output <- returnA -< if reset then 0 else next next <- delay 0 -< output+1 returnA -< output |

In the previous example, we used a conditional expression to construct the input for an arrow. Sometimes we want to conditionally execute different commands, as in

proc (x,y) -> if f x y then g -< x+1 else h -< y+2 |

arr (\ (x,y) -> if f x y then Left x else Right y) >>> (arr (\x -> x+1) >>> f) ||| (arr (\y -> y+2) >>> g) |

There are also `case` commands, like

case input of [] -> f -< () [x] -> g -< x+1 x1:x2:xs -> do y <- h -< (x1, x2) ys <- k -< xs returnA -< y:ys |

As we're seen, arrow notation provides constructs,
modelled on those for expressions,
for sequencing, value recursion and conditionals.
But suitable combinators,
which you can define in ordinary Haskell,
may also be used to build new commands out of existing ones.
The basic idea is that a command defines an arrow from environments to values.
These environments assign values to the free local variables of the command.
Thus combinators that produce arrows from arrows
may also be used to build commands from commands.
For example, the `ArrowChoice` class includes a combinator

ArrowChoice a => (<+>) :: a e c -> a e c -> a e c |

expr' = proc x -> returnA -< x <+> do symbol Plus -< () y <- term -< () expr' -< x + y <+> do symbol Minus -< () y <- term -< () expr' -< x - y |

expr' = (proc x -> returnA -< x) <+> (proc x -> do symbol Plus -< () y <- term -< () expr' -< x + y) <+> (proc x -> do symbol Minus -< () y <- term -< () expr' -< x - y) |

arr k >>> (f <+> g) = (arr k >>> f) <+> (arr k >>> g) |

We could define our own operator

untilA :: ArrowChoice a => a e () -> a e Bool -> a e () untilA body cond = proc x -> if cond x then returnA -< () else do body -< x untilA body cond -< x |

proc x -> do y <- f -< x+1 (|untilA (increment -< x+y) (within 0.5 -< x)|) |

Some operators will need to pass additional inputs to their subcommands. For example, in an arrow type supporting exceptions, the operator that attaches an exception handler will wish to pass the exception that occurred to the handler. Such an operator might have a type

handleA :: ... => a e c -> a (e,Ex) c -> a e c |

body `handleA` \ ex -> handler |

More concretely,
the values on the stack are paired to the right of the environment.
So when designing operators like `handleA` that pass
extra inputs to their subcommands,
More precisely, the type of each argument of the operator (and its result)
should have the form

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

bracketA :: ... => a e b -> a (e,b) c -> a (e,c) d -> a e d runReader :: ... => a e c -> a' (e,State) c runState :: ... => a e c -> a' (e,State) (c,State) |

proc x -> do s <- ... (|runReader (do { ... })|) s |

The command versions of lambda abstraction and application are analogous to
the expression versions.
In particular, the beta and eta rules describe equivalences of commands.
These three features (operators, lambda abstraction and application)
are the core of the notation; everything else can be built using them,
though the results would be somewhat clumsy.
For example, we could simulate `do`-notation by defining

bind :: Arrow a => a e b -> a (e,b) c -> a e c u `bind` f = returnA &&& u >>> f bind_ :: Arrow a => a e b -> a e c -> a e c u `bind_` f = u `bind` (arr fst >>> f) |

cond :: ArrowChoice a => a e b -> a e b -> a (e,Bool) b cond f g = arr (\ (e,b) -> if b then Left e else Right e) >>> f ||| g |

Instead of a single form of arrow application (arrow tail) with two translations, the implementation provides two forms "

`-<`" (first-order) and "`-<<`" (higher-order).User-defined operators are flagged with banana brackets instead of a new

`form`keyword.

Although only GHC implements arrow notation directly, there is also a preprocessor (available from the arrows web page>) that translates arrow notation into Haskell 98 for use with other Haskell systems. You would still want to check arrow programs with GHC; tracing type errors in the preprocessor output is not easy. Modules intended for both GHC and the preprocessor must observe some additional restrictions:

The module must import

`Control.Arrow`.The preprocessor cannot cope with other Haskell extensions. These would have to go in separate modules.

Because the preprocessor targets Haskell (rather than Core),

`let`-bound variables are monomorphic.