I have a value:
my :: [(A, Either B [C])]
and I want to get [(A, C)]
from it using lens. The result items are items from my
that:
Right [C]
Right [C]
has at least 1 item, so the result get the first (head) item from itI know how to get the [C]
but I don't know how to get [(A, C)]
.
You want:
my ^.. each . runFold (second (Fold (_Right . _head)))
The idea is that _Right . _head
is a fold that selects a C
from an Either B [C]
. You can make it select an (A, C)
from an (A, Either B [C])
, using second
from Control.Arrow
. However, to do this, you need to reify the fold (i.e., turn it into a newtype with an Arrow
instance) using Fold
and then unreify it with runFold
. The resulting fold specializes to:
runFold (second (Fold (_Right . _head))) :: Fold (A, Either B [C]) (A,C)
which selects either zero or one instances of (A,C)
, and you can compose it with each
to fold over a traversable container, like a list:
runFold (second (Fold (_Right . _head))) :: Fold [(A, Either B [C])] (A,C)
to select all of the (A,C)
from the container's elements.
Sample code:
import Control.Lens
import Control.Arrow
my :: [(Int, Either Double [Char])]
my = [(1, Right "apple"), (2, Left 1.5), (3, Right "bear"), (4, Right "")]
main = do
print $ my ^.. each . runFold (second (Fold (_Right . _head)))