, ScalaZ, , scalaz.Leibniz . :
sealed abstract class LeibnizK[F[_], G[_]] {
def subst[Z[_[_]]](p: Z[F]): Z[G]
}
object LeibnizK {
implicit def refl[F[_]] = new LeibnizK[F, F] {
override def subst[Z[_[_]]](p: Z[F]): Z[F] = p
}
}
, , , :
type Outer[A] = Option[A]
type Id[A] = A
case class Foo[F[_]](me: F[String]) {
// Oh boy, here comes type lambda
def bar[Inner[_]](implicit leibk: LeibnizK[
F,
({type L[A] = Outer[Inner[A]]})#L
]): Outer[Foo[Inner]] = leibk.subst(this).me.map(Foo(_)) // <- OK to use methods of Outer
}
assert(Foo[Option](Some("meh")).bar[Id] == Some(Foo[Id]("meh")))
. :
λ[A => Outer[Inner[A]]
Lambda[A => Outer[Inner[A]]
({type L[A] = Outer[Inner[A]]})
( )
(?, Int)
({type L[A] = (A, Int)})