Question

I'm trying to grok & work with Arrows, and am having some difficulty. I have a context where I need an Arrow [a] [b], and I want to write an Arrow a b and map/sequence it inside the arrow, a la mapM. Specifically, the arrow is a Hakyll Compiler, but I don't think that matters much for the answer.

Given an arrow

myInnerArrow :: Arrow a => a b c

How can I lift this into an arrow

myOuterArrow :: Arrow a => a [b] [c]

?

I have scoured the base library, particularly in Data.List and Control.Arrow, but I cannot find anything that looks like it will do the job. Does it exist under a name I do not expect? Is it provided by some other library? Is it impossible to write for some reason?

Was it helpful?

Solution

You can't without choice. The lifting function will have this type:

mapA :: (ArrowChoice a) => a b c -> a [b] [c]

The easiest way to implement is by using proc notation:

mapA c =
    proc xs' ->
        case xs' of
            [] -> returnA -< []
            (x:xs) -> uncurry (:) ^<< c *** mapA c -< (x, xs)

Untested code, but should work. Note however that a function that generic is going to be really slow. I recommend writing this mapping function for your arrow specifically.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top