在scala中堆叠Monad变形金刚

Ily*_*gin 7 monads haskell scala monad-transformers scalaz

我正试图以scalaz哈斯克尔的方式堆叠monad transfromers :

statyReader :: (MonadReader Int m, MonadState Int m) => m Int
Run Code Online (Sandbox Code Playgroud)

斯卡拉:

  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
Run Code Online (Sandbox Code Playgroud)

它用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)
                    ^
Run Code Online (Sandbox Code Playgroud)

为什么会这样?我的猜测是编译器现在混淆了F[_]它应该选择的"monadic 实例"(MonadReader和MonadState都扩展Monad[F[_]).这是一个正确的猜测吗?

怎么克服这个?

dev*_*kat 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]
Run Code Online (Sandbox Code Playgroud)

显然,作为一种解决方法,您可以使用两个参数列表来选择要使用的 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
Run Code Online (Sandbox Code Playgroud)