问题
I am looking for a function with type similar to:
Monad m => (a, b) -> (b -> m c) -> m (a, c)
It appears to me as some combination of bind (>>=
) and a lens operation.
I am aware that I can solve this with a pattern match after a bind, but my gut tells me there is a "simpler" way to write this by leveraging lenses.
Is there any such operation?
回答1:
This is definitely lensy. The monad is actually just a bit of a distraction because all you need is a functor:
changesecond (a, b) f = fmap (a,) (f b)
I'm pretty sure the _2
lens can be made to do your bidding with a basic lens thing like maybe over
but I'm not too familiar with the library yet.
Edit
No combinator is really needed. You can write
changesecond pair f = _2 f pair
You should be able to work this out from the general definition of the Lens
type.
Edit 2
This simple example demonstrates the main theme of Van Laarhoven lens construction:
- Extract the focus from the context.
- Apply the given function to produce a functorful of results.
- Use
fmap
to restore the contexts to the results.
Ed Kmett's lens
library elaborates on this theme in various ways. Sometimes it strengthens the functor constraint. Sometimes it generalizes the function to a profunctor. In the case of Equality
, it removes the functor constraint. It just turns out that the same basic type shape can express a lot of different ideas.
回答2:
Your function is just forM = flip mapM
, or for = flip traverse
if you relax the Monad
constraint to Applicative
. The Functor
being traversed is (,) a
.
Prelude> let foo :: Applicative f => (a, b) -> (b -> f c) -> f (a, c); foo p k = traverse k p
Prelude> :t foo
foo :: Applicative f => (a, b) -> (b -> f c) -> f (a, c)
Prelude> foo (1,2) (\x -> [x,2*x])
[(1,2),(1,4)]
(Also, as dfeuer points out, you don't even need Applicative
in this specific case.)
来源:https://stackoverflow.com/questions/31978596/monadic-alteration-to-tuple