Reputation: 27375
I have the following types and declarations:
import scalaz._, Scalaz._
trait Container[T]
type FreeContainer[A] = Free[Container, A]
type FreeFreeContainer[A] = Free[FreeContainer, A]
val fc: FreeContainer[Int]
val ffc: FreeFreeContainer[Int]
val t: Container ~> Id
val tranformed: Int = fc.foldMap(t) //ok
val tranformed2: Int = ffc.foldMap(t) //error
Is it possible to lift Container ~> Id
to FreeContainer ~> Id
?
Upvotes: 1
Views: 82
Reputation: 6537
Yes, via foldMap
:
val t: Container ~> Id
val tt: FreeContainer ~> Id = new (FreeContainer ~> Id) {
def apply[A](fc: FreeContainer[A]): A = fc.foldMap(t)
}
Using the polymorphic lambda syntax of kind-projector, this can be simplified to
val tt: FreeContainer ~> Id = λ[FreeContainer ~> Id](_.foldMap(t))
So you can do
val tranformed2: Int = ffc.foldMap(λ[FreeContainer ~> Id](_.foldMap(t)))
Alternatively, you can just do two consecutive foldMap
s, the first one with the identity natural transformation:
val tranformed2: Int = ffc.foldMap(NaturalTransformation.refl[FreeContainer]).foldMap(t)
Upvotes: 3