Я не вижу ничего подобного.ASetter
определено
type ASetter s t a b = (a -> Identity b) -> s -> Identity t
, поэтому оно недостаточно мощное для работы (и Setter
тоже не может этого сделать).С другой стороны, получается, что Lens
немного сильнее, чем необходимо.Давайте теперь рассмотрим, как это сделать с Traversal
.
type Traversal s t a b =
forall f. Applicative f => (a -> f b) -> s -> f t
Итак
Traversal s s a b =
forall f. Applicative f => (a -> f b) -> s -> f s
Какой Applicative
нам нужен?m
кажется очевидным, чтобы попробовать.Когда мы проходим обход a -> m b
, мы возвращаемся s -> m s
.Большой!Как обычно для lens
, мы фактически потребуем, чтобы пользователь только предоставил ATraversal
, который мы можем клонировать.
modifyingM
:: MonadState s m
=> ATraversal s s a b
-> (a -> m b) -> m ()
modifyingM t f = do
s <- get
s' <- cloneTraversal t f s
put s'
Это хорошо, потому что он проходит через состояние только один раз.
Даже это излишне, правда.Самая естественная вещь на самом деле
modifyingM
:: MonadState s m
=> LensLike m s s a b
-> (a -> m b) -> m ()
modifyingM t f = do
s <- get
s' <- t f s
put s'
Вы можете применить это непосредственно к Traversal
, Lens
, Iso
или Equality
, или использовать cloneTraversal
, cloneLens
, cloneIso
или (в следующей версии lens
, мы надеемся) cloneEquality
, чтобы применить его к мономорфным вариантам.