4

我有这种类型,基本上是 Kleisli 箭头:

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

4

2 回答 2

8

在GHC Trac中搜索ApplicativeDo相关票证后,似乎这是一个已知问题:


显式丢弃结果是一种解决方法:

do
  _ <- pure ()
  pure ()
于 2016-12-18T22:35:02.093 回答
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 (),因为第一个值是 wrap (),而不是函数。由于没有有效的方法可以仅使用Applicative实例对其进行脱糖,因此编译器会查找但未能找到Monad允许的实例pure () >> pure ()

于 2016-12-18T17:03:30.897 回答