将两个monadic值放入一对并返回它

Lin*_*hin 4 monads haskell parsec pointfree applicative

我正在玩Parsec,我希望将两个解析器合并为一个,结果放在一对,然后将另一个函数提供给解析结果来写这样的东西:

try (pFactor <&> (char '*' *> pTerm) `using` (*))
Run Code Online (Sandbox Code Playgroud)

所以我写了这个:

(<&>) :: (Monad m) => m a -> m b -> m (a, b)
pa <&> pb = do
  a <- pa
  b <- pb
  return (a, b)
Run Code Online (Sandbox Code Playgroud)

using :: (Functor f) => f (a, b) -> (a -> b -> c) -> f c
p `using` f = (uncurry f) <$> p
Run Code Online (Sandbox Code Playgroud)

有什么类似的(<&>)已经在某处实现了吗?或者这可以写成免费的吗?我尝试fmap (,)但似乎很难匹配类型.

alt*_*ive 11

<&>liftM2将更好

(,) <$> a <*> b
Run Code Online (Sandbox Code Playgroud)

因为应用风格似乎越来越流行并且非常简洁.对这样的事物使用适用的风格将消除对<&>自身的需要,因为它比它更清晰(,) <$> a <*> b.

此外,这甚至不需要monad - 它也适用于Applicatives.

  • 而且你不需要`using`,你可以使用`(*)`代替`(,)`,就像`(*)<$> a <*> b`一样. (2认同)

bzn*_*bzn 7

有什么类似的(<&>)已经在某处实现了吗?或者这可以自由写点吗?我试过fmap(,),但似乎很难匹配类型.

我现在不在任何地方实施,但<&>应该是相同的liftM2 (,).不同之处fmap在于,将二元函数liftM2提升为monad.


ham*_*mar 6

使用applicative样式,不需要将中间结果放入元组中以立即应用未经证实的函数.只需使用<$>和"直接"应用该功能<*>.

try ((*) <$> pFactor <*> (char '*' *> pTerm))
Run Code Online (Sandbox Code Playgroud)

一般来说,假设Monad和的实例Applicative,

do x0 <- m0
   x1 <- m1
   ...
   return $ f x0 x1 ...
Run Code Online (Sandbox Code Playgroud)

相当于

f <$> m0 <*> m1 <*> ...
Run Code Online (Sandbox Code Playgroud)

除了后一种形式更一般,只需要一个Applicative实例.(所有monad 也应该是applicative functor,尽管语言没有强制执行).