简体   繁体   English

从 Applicative 和 Monad 证明序列定义的等效性

[英]Proving equivalence of sequence definitions from Applicative and Monad

How can I properly prove that我怎样才能正确地证明这一点

sequenceA :: (Traversable t, Applicative f) => t (f a) -> f (t a)
sequenceA []     = pure []
sequenceA (x:xs) = pure (:) <*> x <*> sequenceA xs

is essentially the same to monad inputs as本质上与 monad 输入相同

sequenceA' :: Monad m => [m a] -> m [a]
sequenceA' [] = return [] 
sequenceA' (x:xs) = do 
                    x'  <- x 
                    xs' <- sequenceA' xs 
                    return (x':xs')

In spite of the constraint Applicative and Monad of course.当然,尽管有ApplicativeMonad的约束。

Here's a proof sketch:这是一个证明草图:

  1. Show that显示

    do x' <- x xs' <- sequenceA' xs return (x' : xs')

    is equivalent to相当于

    do f1 <- do cons <- return (:) x' <- x return (cons x') xs' <- sequenceA' xs return (f1 xs')

    This involves desugaring (and resugaring) do notation and applying the Monad laws .这涉及脱糖(和重新加糖) do符号和应用Monad 定律

  2. Use the definition of ap :使用ap定义

     ap m1 m2 = do { x1 <- m1; x2 <- m2; return (x1 x2) }

    to turn the above code into把上面的代码变成

    do f1 <- return (:) `ap` x xs' <- sequenceA' xs return (f1 xs')

    and then进而

    return (:) `ap` x `ap` sequenceA' xs
  3. Now you have现在你有

    sequenceA' [] = return [] sequenceA' (x:xs) = return (:) `ap` x `ap` sequenceA' xs

    Assume that pure and <*> are essentially the same as return and `ap` , respectively, and you're done.假设pure<*>本质上分别与return`ap`相同,那么您就完成了。

    This latter property is also stated in the Applicative documentation : Applicative 文档中也说明了后一个属性:

    If f is also a Monad , it should satisfy如果f也是一个Monad ,它应该满足

    • pure = return

    • (<*>) = ap

Since the Functor-Applicative-Monad proposal , implemented in GHC 7.10, Applicative is a superclass of Monad.由于在 GHC 7.10 中实现的Functor-Applicative-Monad 提案,Applicative 是 Monad 的超类。 So even though your two functions can't be strictly equivalent, since sequenceA 's domain includes sequenceA' 's domain, we can look at what happens in this common domain (the Monad typeclass).因此,即使您的两个函数不能严格等效,因为sequenceA的域包括sequenceA' ' 的域,我们可以看看在这个公共域( Monad类型类)中发生了什么。

This paper shows an interesting demonstration of desugaring do notation to applicative and functor operations ( <$> , pure and <*> ).本文所示脱糖的一个有趣的演示do记号,以应用性和仿函数操作( <$> pure<*> If the expressions on the right hand side of your left-pointing arrows ( <- ) don't depend on each other, as is the case in your question, you can always use applicative operations, and therefore show that your hypothesis is correct (for the Monad domain).如果你的左箭头 ( <- ) 右侧的表达式不相互依赖,就像你的问题一样,你总是可以使用应用运算,因此表明你的假设是正确的(对于Monad域)。

Also have a look at the ApplicativeDo language extension proposal, which contains an example that's just like yours:另请查看ApplicativeDo语言扩展提案,其中包含一个与您类似的示例:

do
  x <- a
  y <- b
  return (f x y)

which translates to:这意味着:

(\x y -> f x y) <$> a <*> b

Substituting f for (:) , we get:f代替(:) ,我们得到:

do
  x <- a
  y <- b
  return (x : y)

... which translates to... ......这翻译成......

(\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

Alternatively, you can make GHC's desugarer work for you by using the ApplicativeDo language extension and by following this answer to the SO question "haskell - Desugaring do-notation for Monads".或者,您可以通过使用ApplicativeDo语言扩展并按照对 SO 问题“haskell - Desugaring do-notation for Monads”的回答来使 GHC 的 desugarer 为您工作。 I'll leave this exercise up to you (as it honestly goes beyond my capacities!).我会把这个练习留给你(因为它真的超出了我的能力!)。

My own two cents我自己的两分钱

There is no do notation for applicatives in Haskell. Haskell 中没有应用程序的 do 符号。 It can be seen specifically in this segment .可以在这部分具体看到。

return and pure do exactly the same, but with different constraints, right?, so this part pure (:) and this part return (x:xs) are essentially the same. returnpure完全一样,但有不同的约束,对吧?所以这部分pure (:)和这部分return (x:xs)本质上是一样的。

Then, here x <- act you are getting the value of act, and then the value of the recursion xs <- seqn acts , to finally wrap it with the return .然后,在这里x <- act你得到的是 act 的值,然后是递归xs <- seqn acts act 的值,最后用return包裹它。

And that's what pure (:) <*> x <*> sequenceA xs is essentially doing.这就是pure (:) <*> x <*> sequenceA xs本质上所做的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM