[英]Proving equivalence of sequence definitions from Applicative and Monad
我怎样才能正确地证明这一点
sequenceA :: (Traversable t, Applicative f) => t (f a) -> f (t a)
sequenceA [] = pure []
sequenceA (x:xs) = pure (:) <*> x <*> sequenceA xs
本质上与 monad 输入相同
sequenceA' :: Monad m => [m a] -> m [a]
sequenceA' [] = return []
sequenceA' (x:xs) = do
x' <- x
xs' <- sequenceA' xs
return (x':xs')
当然,尽管有Applicative
和Monad
的约束。
这是一个证明草图:
显示
do x' <- x xs' <- sequenceA' xs return (x' : xs')
相当于
do f1 <- do cons <- return (:) x' <- x return (cons x') xs' <- sequenceA' xs return (f1 xs')
这涉及脱糖(和重新加糖) do
符号和应用Monad 定律。
ap m1 m2 = do { x1 <- m1; x2 <- m2; return (x1 x2) }
把上面的代码变成
do f1 <- return (:) `ap` x xs' <- sequenceA' xs return (f1 xs')
进而
return (:) `ap` x `ap` sequenceA' xs
现在你有
sequenceA' [] = return [] sequenceA' (x:xs) = return (:) `ap` x `ap` sequenceA' xs
假设pure
和<*>
本质上分别与return
和`ap`
相同,那么您就完成了。
Applicative 文档中也说明了后一个属性:
如果
f
也是一个Monad
,它应该满足
pure = return
(<*>) = ap
由于在 GHC 7.10 中实现的Functor-Applicative-Monad 提案,Applicative 是 Monad 的超类。 因此,即使您的两个函数不能严格等效,因为sequenceA
的域包括sequenceA'
' 的域,我们可以看看在这个公共域( Monad
类型类)中发生了什么。
本文所示脱糖的一个有趣的演示do
记号,以应用性和仿函数操作( <$>
pure
和<*>
如果你的左箭头 ( <-
) 右侧的表达式不相互依赖,就像你的问题一样,你总是可以使用应用运算,因此表明你的假设是正确的(对于Monad
域)。
另请查看ApplicativeDo语言扩展提案,其中包含一个与您类似的示例:
do
x <- a
y <- b
return (f x y)
这意味着:
(\x y -> f x y) <$> a <*> b
用f
代替(:)
,我们得到:
do
x <- a
y <- b
return (x : y)
......这翻译成......
(\x y -> x : y) <$> a <*> b
--And by eta reduction
(:) <$> a <*> b
--Which is equivalent to the code in your question (albeit more general):
pure (:) <*> a <*> b
或者,您可以通过使用ApplicativeDo
语言扩展并按照对 SO 问题“haskell - Desugaring do-notation for Monads”的回答来使 GHC 的 desugarer 为您工作。 我会把这个练习留给你(因为它真的超出了我的能力!)。
我自己的两分钱
Haskell 中没有应用程序的 do 符号。 可以在这部分具体看到。
return
和pure
完全一样,但有不同的约束,对吧?所以这部分pure (:)
和这部分return (x:xs)
本质上是一样的。
然后,在这里x <- act
你得到的是 act 的值,然后是递归xs <- seqn acts
act 的值,最后用return
包裹它。
这就是pure (:) <*> x <*> sequenceA xs
本质上所做的。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.