[英]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.