ApplicativeDo not working with sequencing

两盒软妹~` 提交于 2020-01-14 13:23:48

问题


I have this type, basically a Kleisli arrow:

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

Since it has an Applicative instance, I turn on ApplicativeDo and try to build a value using do-notation:

{-# language ApplicativeDo #-}

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

It doesn't work:

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

Is there a way to make it work? I'm using GHC 8.0.1.


回答1:


After searching for ApplicativeDo-related tickets in the GHC Trac, it appears that is is a known problem:

  • https://ghc.haskell.org/trac/ghc/ticket/10892

  • https://ghc.haskell.org/trac/ghc/ticket/12666


Explicitly discarding the result is a workaround:

do
  _ <- pure ()
  pure ()



回答2:


ApplicativeDo does not mean that do expressions will always be desugared in terms of an applicative functor, but only if it makes sense to do so. Here, it does not. If you have a do expression like

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

note that the order doesn't really matter, so you could desugar this to

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

instead of

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

However, the expression

do
  pure ()
  pure ()

doesn't have any way of being expressed using pure and <*> alone. It is not equivalent to pure () <*> pure (), because the first value wraps (), not a function. Since there is no valid way to desugar this using only an Applicative instance, the compiler looks for, and fails to find, a Monad instance to allow pure () >> pure ().



来源:https://stackoverflow.com/questions/41210599/applicativedo-not-working-with-sequencing

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!