data Fruit = Apple Int
| Banana Color Int
data Color = Red
| Green
let basket = [Apple 3,Banana Red 30,Apple 6]
The goal is to keep Banana
only
How to remove all Apple {} in the list basket
? using traversal (https://hackage.haskell.org/package/lens-5.3.2/docs/Control-Lens-Traversal.html) ?
Once the traversal
is built then I can remove them , modify them (over) , change them (set)
Thank you !
It can't be done using Traversal
s. Neither traverse
from base nor the traversals from lens allow for that.
The reason is that traversals have the important property that they don't change the overall "shape" of the container. They can't add or remove elements. As the docs for Traversable
say:
Functors representing data structures that can be transformed to structures of the same shape
It's true that the lens
documentation says that traversals let you "focus" on certain elements of a structure. But what is meant is that you can set those elements, or modify them. You can't delete them.
If you are looking for a Traversable
-like class for containers that allow (potentially effectful) filtering operations, there's Filterable
and Witherable
from the witherable package.
But in your case, I would simply do something like
removeApples :: [Fruit] -> [Fruit]
removeApples = mapMaybe (\f -> case f of
Apple {} -> Nothing
other -> Just other)
removeApples2 :: [Fruit] -> [Fruit]
removeApples2 = foldMap (\f -> case f of
Apple {} -> []
other -> [other])
removeApples3 :: [Fruit] -> [Fruit]
removeApples3 fruits = do -- list monad
fruit <- fruits
case fruit of
Apple {} -> []
other -> [other]
removeApples4 :: [Fruit] -> [Fruit]
removeApples4 = filter (\f -> case f of
Apple {} -> False
other -> True)