Put two monadic values ​​in a pair and return them

I am playing with Parsec, and I want to combine the two parsers into one with the result inserted into a pair, and then pass it to another function to work with the analysis result to write something like this:

try (pFactor <&> (char '*' *> pTerm) `using` (*)) 

So I wrote this:

 (<&>) :: (Monad m) => ma -> mb -> m (a, b) pa <&> pb = do a <- pa b <- pb return (a, b) 

and

 using :: (Functor f) => f (a, b) -> (a -> b -> c) -> fc p `using` f = (uncurry f) <$> p 

Is there anything similar (<&>) that was implemented somewhere? Or can it be written without meaning? I tried fmap (,) , but it seems hard to match the type.

+4
source share
5 answers

Is there anything similar (<&>) that was implemented somewhere? Or could it be written for sure? I tried fmap (,), but it seems hard to match the type.

I am not now if it is implemented anywhere, but <&> should be the same as liftM2 (,) . The difference in fmap is that liftM2 raises the binary function to the monad.

+7
source

Better than <&> or liftM2 will be

 (,) <$> a <*> b 

as the applicative style seems to be gaining popularity and is very brief. Using the applicative style for such things will eliminate the need for <&> , since it is much clearer than (,) <$> a <*> b .

Also, it does not even require a monad - it will also work for applicators.

+11
source

Using the applicative style, there is no need to put intermediate results in a tuple in order to immediately apply the unprocessed function. Just apply the function "directly" with <$> and <*> .

 try ((*) <$> pFactor <*> (char '*' *> pTerm)) 

In general, assuming the correct Monad and Applicative instances,

 do x0 <- m0 x1 <- m1 ... return $ f x0 x1 ... 

equivalently

 f <$> m0 <*> m1 <*> ... 

except that the latter form is more general and requires only an Applicative instance. (All monads should also be applicative functors, although language does not provide this).

+6
source

Please note that if you go in the opposite direction from Applicative , you will see that the way to combine parsers fits perfectly into Arrow and the implementation of parsers . For instance:.

 import Control.Arrow (<&>) = (&&&) p `using` f = p >>^ uncurry f 
+3
source

Yes, you can use the applicative style, but I do not believe the answers to any of your questions.

Is there some kind of already defined combinator that takes two arbitrary monads and inserts their values ​​into a pair, and then inserts this pair into the context?

Not in any standard packages.

Can you make this last bit point free?

I'm not sure if there is a way to make a curry function with arity greater than 1 point for free. I do not think so.

Hope that answers your questions.

+1
source

All Articles