Applicative不要使用排序

ApplicativeDo not working with sequencing

我有这种,基本上是克莱斯利箭:

{-# language DeriveFunctor #-}

data Plan m i o = Plan  (i -> m o) deriving Functor

instance (Monad m) => Applicative (Plan m i) where
    pure x = Plan (\_ -> pure x)
    Plan f <*> Plan x = Plan (\i -> f i <*> x i)

因为它有一个 Applicative 实例,我打开 ApplicativeDo 并尝试使用 do-notation 构建一个值:

{-# language ApplicativeDo #-}

myplan :: Plan IO () ()
myplan = do
    pure ()
    pure ()

没用:

No instance for (Monad (Plan IO ())) arising from a do statement

有没有办法让它工作?我正在使用 GHC 8.0.1。

ApplicativeDo 并不意味着 do 表达式将 总是 在应用函子方面被脱糖,但前提是这样做有意义.在这里,它没有。如果你有一个 do 表达式,比如

do
  x <- someAction
  y <- someAction
  return (x + y)

请注意,顺序并不重要,因此您可以将其脱糖为

pure (+) <*> someAction <*> someAction

而不是

someAction >>= (\x -> someAction >>= (\y -> return (x + y))

但是,表达式

do
  pure ()
  pure ()

没有任何单独使用pure<*>来表达的方式。 等同于pure () <*> pure (),因为第一个值包装了(),不是函数。由于没有仅使用 Applicative 实例来对其进行脱糖的有效方法,因此编译器查找并未能找到 Monad 实例以允许 pure () >> pure ().

GHC Trac 中搜索与 ApplicativeDo 相关的工单后,似乎是一个已知问题:


明确丢弃结果是一种解决方法:

do
  _ <- pure ()
  pure ()