Domanda

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].

È stato utile?

Soluzione

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 (:)))
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top