What arrows are used for in Haskell

What is it?

An arrow a b c takes input something of type b and outputs c

It is used as a way to model computations.

Some examples of arrows:

-- type representing a computation
data MyArr b c = MyArr (b -> (c,MyArr b c))
instance Arrow MyArr b c where

-- Functions are arrows too
instance Arrow (->) b c where

To run an arrow computation:

-- run a function arrow
runF :: (b -> c) -> b -> c
runF = id

-- run a MyArr arrow, discarding the remaining computation
runMyArr :: MyArr b c -> b -> c
runMyArr (MyArr step) = fst . step

Usecases:

  • Processing lists of inputs

    In this case the computation model can implicitly make use of state without exposing the state to the programmer

    -- run a function arrow over multiple inputs
    runFList :: (b -> c) -> [b] -> [c]
    runFList f = map f
    
    -- run a MyArr over multiple inputs.
    -- Each step of the computation gives the next step to use
    runMyArrList :: MyArr b c -> [b] -> [c]
    runMyArrList _ [] = []
    runMyArrList (MyArr step) (b:bs) = let (this, step') = step b
                                    in this : runMyArrList step' bs
    
  • Combining computations:

    -- function that, given an input n, returns "n+1" and "n*2"
    calc1 :: Int -> (Int,Int)
    calc1 = (+1) &&& (*2)
    
  • Streams:

    Works well for streams probably but I don’t have any examples :P

References: