lens doesn't offer such a combinator in a ready-made form. If instead of runFoo
you had some g :: a -> a
function, you would be able to use (%=)
, which is to over
what use
is to view
, and write simply foo %= g
. Your desired functionality, though, involves interleaving the m
effects introduced by runFoo
in between the getting and setting, which precludes a solution this straightforward.
Searching for missing State Combinator for Lens
-
27-06-2022 - |
문제
I currently have code that looks like this:
do
x <- use foo
foo <~ runFoo x
where foo
is a Lens
to a Foo
field and runFoo :: MonadState m => Foo -> m Foo
I think there should be a way to do this operation in one line, but I cannot find it. I think it ought to have a comment like:
(????) :: MonadState s m => Lens' s a -> (a -> m a) -> m a
Questions:
- Does such a combinator exist? if so what is it?
- When I run into another question like this, what is the best way to search for it (i.e. Usually I would just type this into Hoogle but I've not had good luck doing that with the lens library)
- Is this actually a primitive combinator found in Control.Monad? (I will be slightly embarrassed if this is yet another job for the kleisli arrow)
해결책
다른 팁
The type signature of the function you are looking for is suspiciously close to that of >>=
, but with the first argument different.
In particular, it appears as if use foo :: Monad m => m Foo
and foo <~ runFoo :: Foo -> m Foo
, so you could use bind directly as use foo >>= (\x -> foo <~ runFoo x)
. There's probably an easier/shorter way, but I don't have the full code to play around with. I'd say just stick with using two lines, and if it's a common enough operation, then define your own combinator for it.