문제

I am playing with Parsec and I want to combine two parsers into one with the result put in a pair, and then feed it another function to operate on the parse result to write something like this:

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

So I wrote this:

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

And

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

Is there anything similar to (<&>) which has been implemented somewhere? Or could this be written pointfree? I tried fmap (,) but it seems hard to match the type.

도움이 되었습니까?

해결책

Is there anything similar to (<&>) which has been implemented somewhere? Or could this be written pointfreely? I tried fmap (,) but it seems hard to match the type.

I don't now if it's implemented anywhere, but <&> should be the same as liftM2 (,). The difference to fmap is, that liftM2 lifts a binary function into the monad.

다른 팁

Better than <&> or liftM2 would be

(,) <$> a <*> b

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

Also this doesn't even require a monad - it will work for Applicatives too.

Using applicative style, there is no need to put the intermediate results into a tuple just to immediately apply an uncurried function. Just apply the function "directly" using <$> and <*>.

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

In general, assuming sane instances of Monad and Applicative,

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

is equivalent to

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

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

Note, that if you go the opposite direction from Applicative you'll see that the way you want to combine parsers fits nicely into Arrow paradigm and Arrow parsers implementation. E.g.:

import Control.Arrow

(<&>) = (&&&) 

p `using` f = p >>^ uncurry f 

Yes, you could use applicative style but I don't believe that answers either of your questions.

Is there some already defined combinator that takes two arbitrary monads and sticks their value types in a pair and then sticks that pair in the context?

Not in any of the standard packages.

Can you do that last bit point free?

I'm not sure if there is a way to make a curried function with an arity greater than 1 point free. I don't think there is.

Hope that answers your questions.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top