I'm trying to stack monad transfromers of scalaz in a haskell way:
statyReader :: (MonadReader Int m, MonadState Int m) => m Int
scala:
  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
It compiles with 1 implicit passed, but not with 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)
                    ^
Why is this happening? My guess is that compiler is now confused which "monadic instance of F[_]" it should pick(both MonadReader and MonadState extend Monad[F[_]). Is this a right guess?
How to overcome this?
This is not really an answer, but maybe helps a bit.
I think you're right; it seems like the compiler can't unify the F[_] types of both parameters (I guess since it is a higher-kinded type with multiple possible instances and not a concrete type instance) to a monad type. Compilation works with separate parameter lists since type unification only happens within a parameter list. It can be further illustrated like this:
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]
Obviously, as a workaround you could use two parameter lists to choose which monad you want to use:
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
                        If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With