Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Chaining arrows of types `a b [c]` and `a c d`

Tags:

haskell

arrows

I have an arrow which outputs a list of values (a b [c]) and another arrow which accepts a single value of that type (a c d). What I need basically is a way to chain them or uplift the second arrow to a [c] [d].

like image 720
Nikita Volkov Avatar asked Dec 02 '12 02:12

Nikita Volkov


1 Answers

You cannot do this with just Arrow type class. Lifting a b c into a [b] [c] requires choice between [] and (:) case. Luckily for us, ArrowChoice offers exactly this operation.

mapA :: ArrowChoice a => a b c -> a [b] [c]
mapA f = proc list -> case list of
    []   -> returnA -< []
    x:xs -> do
        y  <- f      -< x
        ys <- mapA f -< xs
        returnA      -< y:ys

Your function is then simply:

chain :: ArrowChoice a => a b [c] -> a c d -> a b [d]
chain f g = f >>> mapA g

Without proc notation, we would need a function that translates list constructors into Either:

listCase :: [a] -> Either () (a, [a])
listCase []     = Left ()
listCase (x:xs) = Right (x,xs)

mapA f = arr listCase >>>
    arr (const []) ||| (f *** mapA f >>> arr (uncurry (:)))
like image 54
Vitus Avatar answered Oct 04 '22 19:10

Vitus