简体   繁体   English

为什么“let”语句强制“applicative do”块需要monad约束?

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

Consider this example:考虑这个例子:

{-# 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'

Looks nice: But no:看起来不错:但没有:

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

Even this fails:即使这失败了:

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

So, introducing any let statement removes the "applicative" from the "applicative do" .因此,引入任何let语句都会从"applicative do"中删除"applicative " 。 Why?为什么?

It would translate into它会转化为

let unrelated = 1 in return $ Tuple x y'

which doesn't have the form return <something> , and applicative do requires the last statement to be a return or pure :它没有形式return <something> ,而 applicative do 要求最后一个语句是returnpure

In general, the rule for when a do statement incurs a Monad constraint is as follows.一般而言,do 语句何时引发Monad约束的规则如下。 If the do-expression has the following form:如果 do 表达式具有以下形式:

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

where none of the variables defined by p1...pn are mentioned in E1...En , and p1...pn are all variables or lazy patterns, then the expression will only require Applicative .其中没有任何由p1...pn定义的变量在E1...En中被提及,并且p1...pn都是变量或惰性模式,那么表达式将只需要Applicative Otherwise, the expression will require Monad .否则,表达式将需要Monad The block may return a pure expression E depending upon the results p1...pn with either return or pure .该块可能会返回一个纯表达式E取决于结果p1...pnreturnpure

Note: the final statement must match one of these patterns exactly:注意:最后的语句必须完全匹配以下模式之一:

 return E return $ E pure E pure $ E

otherwise GHC cannot recognise it as a return statement, and the transformation to use <$> that we saw above does not apply.否则 GHC 无法将其识别为 return 语句,并且我们上面看到的使用<$>的转换不适用。 In particular, slight variations such as return. Just $ x特别是return. Just $ x return. Just $ x or let x = e in return x would not be recognised. return. Just $ xlet x = e in return x不会被识别。

If you look at the description of desugaring in https://gitlab.haskell.org/ghc/ghc/wikis/applicative-do , it also doesn't support let in any way.如果您查看https://gitlab.haskell.org/ghc/ghc/wikis/applicative-do中的脱糖描述,它也不支持let以任何方式。

What applicative expression would you like this to desugar to?你希望这个去糖的应用表达是什么? A monadic expression is a series of chained scopes, so it makes sense for a let to introduce a binding that extends over all the remaining scopes, but with applicative the various expressions can't really depend on each other, so there's no scope that it makes sense to desugar the let into. monadic 表达式是一系列链式作用域,因此let引入一个扩展到所有剩余作用域的绑定是有意义的,但是通过应用程序,各种表达式不能真正相互依赖,所以它没有 scope对let into 进行脱糖是有意义的。

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

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