# Haskell Language Arrows Function compositions with multiple channels

## Example

`Arrow` is, vaguely speaking, the class of morphisms that compose like functions, with both serial composition and “parallel composition”. While it is most interesting as a generalisation of functions, the `Arrow (->)` instance itself is already quite useful. For instance, the following function:

``````spaceAround :: Double -> [Double] -> Double
spaceAround x ys = minimum greater - maximum smaller
where (greater, smaller) = partition (>x) ys
``````

can also be written with arrow combinators:

``````spaceAround x = partition (>x) >>> minimum *** maximum >>> uncurry (-)
``````

This kind of composition can best be visualised with a diagram:

``````                       ──── minimum ────
╱           *            ╲
──── partition (>x) >>>        *        >>>  uncurry (-) ───
╲           *            ╱
──── maximum ────
``````

Here,

• The `>>>` operator is just a flipped version of the ordinary `.` composition operator (there's also a `<<<` version that composes right-to-left). It pipes the data from one processing step to the next.

• the out-going `╱` `╲` indicate the data flow is split up in two “channels”. In terms of Haskell types, this is realised with tuples:

``````partition (>x) :: [Double] -> ([Double], [Double])
``````

splits up the flow in two `[Double]` channels, whereas

``````uncurry (-) :: (Double,Double) -> Double
``````

merges two `Double` channels.

• `***` is the parallel composition operator. It lets `maximum` and `minimum` operate independently on different channels of the data. For functions, the signature of this operator is

``````(***) :: (b->c) -> (β->γ) -> (b,β)->(c,γ)
``````

At least in the Hask category (i.e. in the `Arrow (->)` instance), `f***g` does not actually compute `f` and `g` in parallel as in, on different threads. This would theoretically be possible, though.