Reputation: 6793
Is there any way to apply the combinators/setters mentioned at Control-Lens-Setter.html#g:4 when the input value (not the field being set), is a Just x
?
For example, considering the (~+)
combinator, if I have the following:
let target = (1, 2)
input1 = Just 10
input2 = Nothing
I want a setter that does the following:
(11, 2) == target & (_1 . someSetter) +~ input1
& (_2 . someSetter) +~ input2
I'm trying to avoid using fmap
or maybe/fromMaybe
in this case, because I have a lot of such operations to do, and would prefer avoiding the boilerplate by leveraging the terseness/conciseness of lenses.
Upvotes: 3
Views: 215
Reputation: 74204
You could always define your own setter.
maybeSetter :: (b -> a -> a) -> ASetter s t a a -> Maybe b -> s -> t
maybeSetter g f x = runIdentity . f (Identity . maybe id g x)
(+!) :: Num a => ASetter s t a a -> Maybe a -> s -> t
(+!) = maybeSetter (+)
let target = (1, 2)
input1 = Just 10
input2 = Nothing
in
(11, 2) == target & (_1 . someSetter) +! input1
& (_2 . someSetter) +! input2
You can also define other setters easily.
(-!) :: Num a => ASetter s t a a -> Maybe a -> s -> t
(-!) = maybeSetter subtract
(||!) :: ASetter s t Bool Bool -> Maybe Bool -> s -> t
(||!) = maybeSetter (||)
(<>!) :: Semigroup a => ASetter s t a a -> Maybe a -> s -> t
(<>!) = maybeSetter (flip (<>))
(.!) :: ASetter s t a a -> Maybe a -> s -> t
(.!) = maybeSetter const
(%!) :: ASetter s t a a -> Maybe (a -> a) -> s -> t
(%!) = maybeSetter id
That's the cool thing about lenses. They are just regular functions.
Upvotes: 5