listzipper
listzipper copied to clipboard
[Feature] map with different functions for selected and not selected elements
Hi, there,
great library! I'm missing a mapping function where one can provide two different functions for mapping elements, depending on the element being selected or not.
My use case is a view that renders the selected element different. It won't work with mixing mapCurrent
with mapBefore/After
(without an intermediate step), because they're a -> a
. map
is from a -> b
but the information if it's current is not provided.
Examples from other libraries
mapCS : (a -> b) -> (a -> b) -> Pivot a -> Pivot b
https://package.elm-lang.org/packages/yotamDvir/elm-pivot/latest/Pivot#mapCS
selectedMap : (Position -> SelectList a -> b) -> SelectList a -> List b
https://package.elm-lang.org/packages/miyamoen/select-list/latest/SelectList#selectedMap
Implementation
Here are three sample implementations for the feature. The api, name and implementation of the function can be discussed :)
mapBoth1 : { mapCurrent : a -> b, mapElse : a -> b } -> Zipper a -> Zipper b
mapBoth1 { mapCurrent, mapElse } zipper =
let
mapFn a =
if a == Zipper.current zipper then
mapCurrent a
else
mapElse a
in
Zipper.map mapFn zipper
mapBoth2 : { mapCurrent : a -> b, mapElse : a -> b } -> Zipper a -> Zipper b
mapBoth2 { mapCurrent, mapElse } zipper =
Zipper.from
(zipper |> Zipper.before |> List.map mapElse)
(zipper |> Zipper.current |> mapCurrent)
(zipper |> Zipper.after |> List.map mapElse)
mapBoth3 : (Bool -> a -> b) -> Zipper a -> Zipper b
mapBoth3 f zipper =
Zipper.map (\a -> f (a == Zipper.current zipper) a) zipper
Hi, @andys8,
Sorry for not getting back to you sooner. I like your proposal. Would you prefer an object with mapCurrent
and mapElse
over two functions (that, admittedly, can be ambiguous as the type signature is the same)? In any case, I think I prefer the function signature of mapBoth1
and mapBoth2
over that of mapBoth3
.
All function names (mapBoth
, mapCS
and selectMap
) are fine with me (although I wouldn't be able to predict what the function does from neither of those names)
With regards to the implementation: I think that destructuring the Zipper
would be easiest. In that case you don't have to check each element to see if it is the focus of the zipper (you know that already).
Would you be willing to make a pull request for this?
I realize that this is basically a :+1:
comment, so apologies if it's unwelcome, but I also just ran into an occasion where I would have liked a function like the ones proposed here!
I'm working on a different project and I once again found that I would have loved to have this function. Should you find the time to merge https://github.com/wernerdegroot/listzipper/pull/29 @wernerdegroot, I would definitely be grateful for it!