我正在玩Parsec,我希望将两个解析器组合成一个结果放入一对,然后将另一个函数提供给解析结果来编写如下内容:
try (pFactor <&> (char '*' *> pTerm) `using` (*))
所以我写了这个:
(<&>) :: (Monad m) => m a -> m b -> m (a, b)
pa <&> pb = do
a <- pa
b <- pb
return (a, b)
和
using :: (Functor f) => f (a, b) -> (a -> b -> c) -> f c
p `using` f = (uncurry f) <$> p
有什么类似的(&lt;&amp;&gt;)已经在某处实现了吗?或者这可以写成免费的吗?我试过fmap (,)
,但似乎很难匹配类型。
答案 0 :(得分:11)
优于<&>
或liftM2
(,) <$> a <*> b
因为应用风格似乎越来越受欢迎并且非常简洁。对这样的事情使用适用的风格将消除<&>
本身的需要,因为它比(,) <$> a <*> b
更清晰。
此外,这甚至不需要monad - 它也适用于Applicatives。
答案 1 :(得分:7)
有什么类似的(&lt;&amp;&gt;)已经在某处实现了吗?或者这可以自由写点吗?我试过fmap(,),但似乎很难匹配类型。
我现在不在任何地方实施,但<&>
应与liftM2 (,)
相同。与fmap
的区别在于,liftM2
将二进制函数提升为monad。
答案 2 :(得分:6)
使用applicative样式,不需要将中间结果放入元组中,只需立即应用未经验证的函数即可。只需使用<$>
和<*>
“直接”应用此功能。
try ((*) <$> pFactor <*> (char '*' *> pTerm))
一般来说,假设Monad
和Applicative
,
do x0 <- m0
x1 <- m1
...
return $ f x0 x1 ...
相当于
f <$> m0 <*> m1 <*> ...
除了后一种形式更通用,只需要一个Applicative
实例。 (所有monad 也应该是应用函子,尽管该语言不强制执行此操作。)
答案 3 :(得分:3)
请注意,如果您从Applicative
开始向相反的方向发展,那么您将看到您希望组合解析器的方式非常适合Arrow范例和Arrow parsers实现。
E.g:
import Control.Arrow
(<&>) = (&&&)
p `using` f = p >>^ uncurry f
答案 4 :(得分:1)
是的,你可以使用适用的风格,但我不相信你的任何一个问题的答案。
是否有一些已经定义的组合器需要两个任意的monad并将它们的值类型绑定在一对中,然后在上下文中粘贴该对?
不在任何标准套餐中。
你可以免费获得最后一点吗?
我不确定是否有办法使用大于1点的arity来制作一个curried函数。我认为没有。
希望能回答你的问题。