The method call get[Int]
returns an IndexedStateT[Id, Int, Int, Int]
. Your Stack[Int]
expands to IndexedStateT[Inner, Int, Int, Int]
where Inner
is an EitherT[Id, String, A]
. This is a bit hard to reason about, so I will simplify your example a bit.
Instead of the Inner
type alias we create a StateT
with an Option
.
type Stack[A] = StateT[Option, Int, A]
The assignment of get[Int]
will still fail.
val x:Stack[Int] = get[Int]
//type mismatch;
// found : scalaz.State[Int,Int]
// (which expands to) scalaz.IndexedStateT[scalaz.Id.Id,Int,Int,Int]
// required: Minimal.Stack[Int]
// (which expands to) scalaz.IndexedStateT[Option,Int,Int,Int]
In order to fix this problem we need to lift
the transformer to an Option
:
val x:Stack[Int] = get[Int].lift[Option]
If you translate that to your example code, you would need to lift
the State
to an Inner
like this. Note that you need to change your definition of Inner
to be covariant as well:
type Inner[+A] = EitherT[Id, String, A]
type Stack[A] = StateT[Inner, Int, A]
val x:Stack[Int] = get[Int].lift[Inner]
To be able to write this without lifting manually you could introduce an implicit conversion. The full example:
type Inner[+A] = EitherT[Id, String, A]
type Outer[F[+_], A] = StateT[F, Int, A]
type Stack[A] = Outer[Inner, A]
implicit def liftToStack[A](x:Outer[Id, A]):Stack[A] = x.lift[Inner]
def foo: Stack[Int] = for {
n <- get[Int]
} yield {
2 * n
}