Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rename interpret and replace ~> #1433

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 14 additions & 9 deletions free/src/main/scala/cats/free/FreeT.scala
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ package free

import scala.annotation.tailrec

import cats.arrow.FunctionK

/**
* FreeT is a monad transformer for Free monads over a Functor S
*
Expand All @@ -27,19 +29,22 @@ sealed abstract class FreeT[S[_], M[_], A] extends Product with Serializable {
* Changes the underlying `Monad` for this `FreeT`, ie.
* turning this `FreeT[S, M, A]` into a `FreeT[S, N, A]`.
*/
def hoist[N[_]](mn: M ~> N): FreeT[S, N, A] =
def hoist[N[_]](mn: FunctionK[M, N]): FreeT[S, N, A] =
step match {
case e @ FlatMapped(_, _) =>
FlatMapped(e.a.hoist(mn), e.f.andThen(_.hoist(mn)))
case Suspend(m) =>
Suspend(mn(m))
}

@deprecated("Use compile", "0.8.0")
def interpret[T[_]](st: FunctionK[S, T])(implicit M: Functor[M]): FreeT[T, M, A] = compile(st)

/** Change the base functor `S` for a `FreeT` action. */
def interpret[T[_]](st: S ~> T)(implicit M: Functor[M]): FreeT[T, M, A] =
def compile[T[_]](st: FunctionK[S, T])(implicit M: Functor[M]): FreeT[T, M, A] =
step match {
case e @ FlatMapped(_, _) =>
FlatMapped(e.a.interpret(st), e.f.andThen(_.interpret(st)))
FlatMapped(e.a.compile(st), e.f.andThen(_.compile(st)))
case Suspend(m) =>
Suspend(M.map(m)(_.left.map(s => st(s))))
}
Expand All @@ -48,7 +53,7 @@ sealed abstract class FreeT[S[_], M[_], A] extends Product with Serializable {
* Runs to completion, mapping the suspension with the given transformation
* at each step and accumulating into the monad `M`.
*/
def foldMap(f: S ~> M)(implicit M: Monad[M]): M[A] = {
def foldMap(f: FunctionK[S, M])(implicit M: Monad[M]): M[A] = {
def go(ft: FreeT[S, M, A]): M[Either[FreeT[S, M, A], A]] =
ft match {
case Suspend(ma) => M.flatMap(ma) {
Expand Down Expand Up @@ -170,13 +175,13 @@ object FreeT extends FreeTInstances {
def roll[S[_], M[_], A](value: S[FreeT[S, M, A]])(implicit M: Applicative[M]): FreeT[S, M, A] =
liftF[S, M, FreeT[S, M, A]](value).flatMap(identity)

def interpret[S[_], T[_], M[_]: Functor](st: S ~> T): FreeT[S, M, ?] ~> FreeT[T, M, ?] =
new ~>[FreeT[S, M, ?], FreeT[T, M, ?]] {
def apply[A](f: FreeT[S, M, A]) = f.interpret(st)
def compile[S[_], T[_], M[_]: Functor](st: FunctionK[S, T]): FunctionK[FreeT[S, M, ?], FreeT[T, M, ?]] =
new FunctionK[FreeT[S, M, ?], FreeT[T, M, ?]] {
def apply[A](f: FreeT[S, M, A]) = f.compile(st)
}

def foldMap[S[_], M[_]: Monad](fk: S ~> M): FreeT[S, M, ?] ~> M =
new ~>[FreeT[S, M, ?], M] {
def foldMap[S[_], M[_]: Monad](fk: FunctionK[S, M]): FunctionK[FreeT[S, M, ?], M] =
new FunctionK[FreeT[S, M, ?], M] {
def apply[A](f: FreeT[S, M, A]) = f.foldMap(fk)
}
}
Expand Down
10 changes: 5 additions & 5 deletions free/src/test/scala/cats/free/FreeTTests.scala
Original file line number Diff line number Diff line change
Expand Up @@ -101,20 +101,20 @@ class FreeTTests extends CatsSuite {
val d: FreeT[JustFunctor, JustFunctor, Int] = transLiftInstance.liftT[JustFunctor, Int](JustFunctor(1))
}

test("interpret to universal id equivalent to original instance") {
test("compile to universal id equivalent to original instance") {
forAll { a: FreeTOption[Int] =>
val b = a.interpret(FunctionK.id)
val b = a.compile(FunctionK.id)
Eq[FreeTOption[Int]].eqv(a, b) should ===(true)
val fk = FreeT.interpret[Option, Option, Option](FunctionK.id)
val fk = FreeT.compile[Option, Option, Option](FunctionK.id)
a should === (fk(a))
}
}

test("interpret stack-safety") {
test("compile stack-safety") {
val a = (0 until 50000).foldLeft(Applicative[FreeTOption].pure(()))(
(fu, i) => fu.flatMap(u => Applicative[FreeTOption].pure(u))
)
val b = a.interpret(FunctionK.id) // used to overflow
val b = a.compile(FunctionK.id) // used to overflow
}

test("foldMap consistent with runM") {
Expand Down