Stacking Monad Transformers in scala

I am trying to build monad transfromers scalaz using the haskell method:

 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? I assume that the compiler is now confused which "monadic instance of F[_] " he should choose (both MonadReader and MonadState extend Monad[F[_] ). Is it correct?

How to overcome this?

+6
source share
1 answer

This is actually not an answer, but maybe a little helps.

I think you're right; it seems that the compiler cannot combine the F[_] types of both parameters (I assume it is a higher type with several possible instances, and not a specific type instance) for the monad type. Compilation works with separate parameter lists, since type unification occurs only in the parameter list. This can be illustrated as follows:

 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 can 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 
+1
source

All Articles