簡體   English   中英

為什么“let”語句強制“applicative do”塊需要monad約束?

[英]Why does a “let” statement force an “applicative do” block into requiring a monad constraint?

考慮這個例子:

{-# language ApplicativeDo #-}

module X where

data Tuple a b = Tuple a b deriving Show

instance Functor (Tuple a) where
    fmap f (Tuple x y) = Tuple x (f y)

instance Foldable (Tuple a) where
    foldr f z (Tuple _ y) = f y z

instance Traversable (Tuple a) where
    traverse f (Tuple x y) = do
        y' <- f y
        let t' = Tuple x y'
        return $ t'

看起來不錯:但沒有:

[1 of 1] Compiling X                ( X.hs, interpreted )

X.hs:15:9: error:
    • Could not deduce (Monad f) arising from a do statement
      from the context: Applicative f
        bound by the type signature for:
                   traverse :: forall (f :: * -> *) a1 b.
                               Applicative f =>
                               (a1 -> f b) -> Tuple a a1 -> f (Tuple a b)
        at X.hs:14:5-12
      Possible fix:
        add (Monad f) to the context of
          the type signature for:
            traverse :: forall (f :: * -> *) a1 b.
                        Applicative f =>
                        (a1 -> f b) -> Tuple a a1 -> f (Tuple a b)
    • In a stmt of a 'do' block: y' <- f y
      In the expression:
        do y' <- f y
           let t' = Tuple x y'
           return $ t'
      In an equation for ‘traverse’:
          traverse f (Tuple x y)
            = do y' <- f y
                 let t' = ...
                 return $ t'
   |
15 |         y' <- f y
   |         ^^^^^^^^^
Failed, no modules loaded.

即使這失敗了:

instance Traversable (Tuple a) where
    traverse f (Tuple x y) = do
        y' <- f y
        let unrelated = 1
        return $ Tuple x y'

因此,引入任何let語句都會從"applicative do"中刪除"applicative " 。 為什么?

它會轉化為

let unrelated = 1 in return $ Tuple x y'

它沒有形式return <something> ,而 applicative do 要求最后一個語句是returnpure

一般而言,do 語句何時引發Monad約束的規則如下。 如果 do 表達式具有以下形式:

 do p1 <- E1; ...; pn <- En; return E

其中沒有任何由p1...pn定義的變量在E1...En中被提及,並且p1...pn都是變量或惰性模式,那么表達式將只需要Applicative 否則,表達式將需要Monad 該塊可能會返回一個純表達式E取決於結果p1...pnreturnpure

注意:最后的語句必須完全匹配以下模式之一:

 return E return $ E pure E pure $ E

否則 GHC 無法將其識別為 return 語句,並且我們上面看到的使用<$>的轉換不適用。 特別是return. Just $ x return. Just $ xlet x = e in return x不會被識別。

如果您查看https://gitlab.haskell.org/ghc/ghc/wikis/applicative-do中的脫糖描述,它也不支持let以任何方式。

你希望這個去糖的應用表達是什么? monadic 表達式是一系列鏈式作用域,因此let引入一個擴展到所有剩余作用域的綁定是有意義的,但是通過應用程序,各種表達式不能真正相互依賴,所以它沒有 scope對let into 進行脫糖是有意義的。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM