【问题标题】:Stacking Monad Transformers in scala在scala中堆叠Monad Transformers
【发布时间】:2016-07-21 16:10:52
【问题描述】:

我正在尝试以 Haskell 方式堆叠 scalaz 的 monad transfromers:

statyReader :: (MonadReader Int m, MonadState Int m) => m Int

斯卡拉:

  def statyReader[F[_]](implicit r: MonadReader[F, Int], s: MonadState[F, Int]): F[Int] = for {
    counter <- s.get
    secret  <- r.ask
    _       <- s.put(counter + secret)
  } yield counter

它编译时使用 1 隐式传递,但不是 2:

Error:(13, 18) value flatMap is not a member of type parameter F[Int]
    counter <- s.get
                 ^
Error:(14, 18) value flatMap is not a member of type parameter F[Int]
    secret  <- r.ask
                 ^
Error:(15, 21) value map is not a member of type parameter F[Unit]
    _       <- s.put(counter + secret)
                    ^

为什么会这样?我的猜测是编译器现在很困惑它应该选择哪个“F[_]”的单子实例(MonadReader 和 MonadState 都扩展了Monad[F[_])。这是一个正确的猜测吗?

如何克服这个问题?

【问题讨论】:

  • 次要观点:在 Haskell 中,我不会将其称为“堆叠 monad 转换器”,因为我会用它来指代例如StateT s (ReaderT r IO) a。不过,确实,在这样的堆栈中,我们会有多个类型约束,所以它是相关的。
  • 我不认为这两个隐式参数是问题,否则你会得到错误“模糊隐式值”(见github.com/scalaz/scalaz/issues/1110)。
  • @devkat 如果我只通过 1 个隐含的,事情就可以了 :)
  • 对不起,我的评论是没有根据的 :) 有趣的是,当一个参数是显式的而另一个是隐式的时,它会起作用;如果两者都是显式的或隐式的,它就不起作用。
  • 实际上它适用于 1 隐式并且不适用于 1 显式(例如justReader[F[_]](r: MonadReader[F, Int]) vs justReader[F[_]](implicit r: MonadReader[F, Int])),所以我现在完全迷路了。

标签: scala haskell monads scalaz monad-transformers


【解决方案1】:

这不是一个真正的答案,但可能会有所帮助。

我认为你是对的;似乎编译器无法将两个参数的 F[_] 类型(我猜是因为它是具有多个可能实例而不是具体类型实例的高级类型)统一为 monad 类型。编译使用单独的参数列表,因为类型统一只发生在参数列表中。可以进一步说明如下:

def statyReader[F[_]](implicit r: MonadReader[F, Int], s: MonadState[F, Int]): F[Int] =
  statyReader2(r, s)

def statyReader2[F[_]:Monad](r: MonadReader[F, Int], s: MonadState[F, Int]): F[Int] =
  for {
    counter <- s.get
    secret <- r.ask
    _ <- s.put(counter + secret)
  } yield counter

Error: ambiguous implicit values: both
value s of type scalaz.MonadState[F,Int] and
value r of type scalaz.MonadReader[F,Int]
match expected type scalaz.Monad[F]

显然,作为一种解决方法,您可以使用两个参数列表来选择要使用的 monad:

def statyReader[F[_]](implicit r: MonadReader[F, Int], s: MonadState[F, Int]): F[Int] =
  statyReader2(r)(s)

def statyReader2[F[_]](r: MonadReader[F, Int])(implicit s: MonadState[F, Int]): F[Int] =
  for {
    counter <- s.get
    secret <- r.ask
    _ <- s.put(counter + secret)
  } yield counter

【讨论】:

    猜你喜欢
    • 2023-03-29
    • 1970-01-01
    • 1970-01-01
    • 2014-05-03
    • 1970-01-01
    • 2019-10-29
    • 1970-01-01
    • 2012-10-12
    • 1970-01-01
    相关资源
    最近更新 更多