Применить линзу «сеттер» только тогда, когда входное значение равно «Just x»? - PullRequest
3 голосов
/ 26 сентября 2019

Есть ли способ применить комбинаторы / сеттеры, упомянутые в Control-Lens-Setter.html # g: 4 , когда входное значение ( не задается поле), это Just x?

Например, учитывая комбинатор (~+), если у меня есть следующее:

let target = (1, 2)
    input1 = Just 10
    input2 = Nothing

Я хочу установить, который делаетследующее:

(11, 2) == target & (_1 . someSetter) +~ input1 
                  & (_2 . someSetter) +~ input2

Я пытаюсь избегать использования fmap или maybe/fromMaybe в этом случае, потому что у меня много таких операций, и я предпочел бы избегать шаблонов, используя краткость/ краткость линз.

1 Ответ

5 голосов
/ 26 сентября 2019

Вы всегда можете определить свой собственный сеттер.

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

Вы также можете легко определить другие сеттеры.

(-!) :: 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

Это классная вещь в объективах.Это просто обычные функции.

...