Permalink
Browse files

Renamed Free to FreeC to make it clear it is more than standard Free

  • Loading branch information...
mpilquist committed Jun 10, 2017
1 parent bf667b7 commit 31605b73436b553d7ea7086386308c2dcf53e1d1

This file was deleted.

Oops, something went wrong.
@@ -0,0 +1,25 @@
package fs2
package benchmark
import cats.effect.IO
import org.openjdk.jmh.annotations.{Benchmark, State, Scope}
import fs2.internal.FreeC
@State(Scope.Thread)
class FreeCBenchmark {
val N = 1000000
@Benchmark
def nestedMaps = {
val nestedMapsFreeC = (0 to N).foldLeft(FreeC.Pure[IO,Int](0): FreeC[IO,Int]) { (acc, i) => acc.map(_ + i) }
nestedMapsFreeC.run
}
@Benchmark
def nestedFlatMaps = {
val nestedFlatMapsFreeC = (0 to N).foldLeft(FreeC.Pure[IO,Int](0): FreeC[IO,Int]) { (acc, i) => acc.flatMap(j => FreeC.Pure(i + j)) }
nestedFlatMapsFreeC.run
}
}
@@ -6,22 +6,22 @@ import cats.~>
import cats.effect.Effect
import cats.implicits._
import fs2.internal.{ Algebra, Free }
import fs2.internal.{ Algebra, FreeC }
/** Result of `unconsAsync`. Conceptually similar to a `Future`. Can be forced via `pull` or `stream`. */
sealed abstract class AsyncPull[F[_],A] { self =>
protected def get: Free[F, A]
protected def get: FreeC[F, A]
protected def cancellableGet: Free[F, (Free[F, A], Free[F, Unit])]
protected def cancellableGet: FreeC[F, (FreeC[F, A], FreeC[F, Unit])]
/** Converts to a pull, that when flat mapped, semantically blocks on the result. */
def pull: Pull[F,Nothing,A] = Pull.fromFree(get.translate[Algebra[F,Nothing,?]](new (F ~> Algebra[F,Nothing,?]) {
def pull: Pull[F,Nothing,A] = Pull.fromFreeC(get.translate[Algebra[F,Nothing,?]](new (F ~> Algebra[F,Nothing,?]) {
def apply[X](fx: F[X]) = Algebra.Eval(fx)
}))
/** Converts to a stream, that when flat mapped, semantically blocks on the result. */
def stream: Stream[F,A] = Stream.fromFree(get.translate[Algebra[F,A,?]](new (F ~> Algebra[F,A,?]) {
def stream: Stream[F,A] = Stream.fromFreeC(get.translate[Algebra[F,A,?]](new (F ~> Algebra[F,A,?]) {
def apply[X](fx: F[X]) = Algebra.Eval(fx)
}).flatMap(Algebra.output1))
@@ -34,7 +34,7 @@ sealed abstract class AsyncPull[F[_],A] { self =>
/** Returns a new async pull that completes with the result of the first async pull that completes between this and `b`. */
def race[B](b: AsyncPull[F,B])(implicit F: Effect[F], ec: ExecutionContext): AsyncPull[F,Either[A,B]] = new AsyncPull[F, Either[A,B]] {
def get = cancellableGet.flatMap(_._1)
def cancellableGet = Free.Eval(for {
def cancellableGet = FreeC.Eval(for {
ref <- async.ref[F,Either[A,B]]
t0 <- self.cancellableGet.run
(a, cancelA) = t0
@@ -43,10 +43,10 @@ sealed abstract class AsyncPull[F[_],A] { self =>
_ <- ref.setAsync(a.run.map(Left(_)))
_ <- ref.setAsync(b.run.map(Right(_)))
} yield {
(Free.Eval(ref.get.flatMap {
(FreeC.Eval(ref.get.flatMap {
case Left(a) => cancelB.run.as(Left(a): Either[A, B])
case Right(b) => cancelA.run.as(Right(b): Either[A, B])
}), Free.Eval(cancelA.run >> cancelB.run))
}), FreeC.Eval(cancelA.run >> cancelB.run))
})
}
@@ -76,15 +76,15 @@ object AsyncPull {
/** Lifts a pure value in to [[AsyncPull]]. */
def pure[F[_],A](a: A): AsyncPull[F,A] = new AsyncPull[F,A] {
def get = Free.Pure(a)
def cancellableGet = Free.Pure((get, Free.Pure(())))
def get = FreeC.Pure(a)
def cancellableGet = FreeC.Pure((get, FreeC.Pure(())))
}
/** Returns an async pull that gets its value from reading the specified ref. */
def readRef[F[_],A](r: async.Ref[F,A]): AsyncPull[F,A] =
new AsyncPull[F,A] {
def get = Free.Eval(r.get)
def cancellableGet = Free.Eval(r.cancellableGet).map { case (get, cancel) => (Free.Eval(get), Free.Eval(cancel)) }
def get = FreeC.Eval(r.get)
def cancellableGet = FreeC.Eval(r.cancellableGet).map { case (get, cancel) => (FreeC.Eval(get), FreeC.Eval(cancel)) }
}
/**
@@ -93,9 +93,9 @@ object AsyncPull {
*/
def readAttemptRef[F[_],A](r: async.Ref[F,Either[Throwable,A]]): AsyncPull[F,A] =
new AsyncPull[F,A] {
def get = Free.Eval(r.get).flatMap(_.fold(Free.Fail(_), Free.Pure(_)))
def cancellableGet = Free.Eval(r.cancellableGet).map { case (get, cancel) =>
(Free.Eval(get).flatMap(_.fold(Free.Fail(_), Free.Pure(_))), Free.Eval(cancel))
def get = FreeC.Eval(r.get).flatMap(_.fold(FreeC.Fail(_), FreeC.Pure(_)))
def cancellableGet = FreeC.Eval(r.cancellableGet).map { case (get, cancel) =>
(FreeC.Eval(get).flatMap(_.fold(FreeC.Fail(_), FreeC.Pure(_))), FreeC.Eval(cancel))
}
}
}
@@ -6,18 +6,18 @@ import cats.effect.Effect
import cats.implicits._
import fs2.async.mutable.Queue
import fs2.internal.Free
import fs2.internal.FreeC
object Pipe {
/** Creates a [[Stepper]], which allows incrementally stepping a pure pipe. */
def stepper[I,O](p: Pipe[Pure,I,O]): Stepper[I,O] = {
type ReadSegment[R] = Option[Segment[I,Unit]] => R
type Read[R] = Free[ReadSegment, R]
type Read[R] = FreeC[ReadSegment, R]
type UO = Option[(Segment[O,Unit],Stream[Read,O])]
def prompts: Stream[Read,I] =
Stream.eval[Read,Option[Segment[I,Unit]]](Free.Eval(identity)).flatMap {
Stream.eval[Read,Option[Segment[I,Unit]]](FreeC.Eval(identity)).flatMap {
case None => Stream.empty
case Some(segment) => Stream.segment(segment).append(prompts)
}
@@ -30,14 +30,14 @@ object Pipe {
def go(s: Read[UO]): Stepper[I,O] = Stepper.Suspend { () =>
s.viewL.get match {
case Free.Pure(None) => Stepper.Done
case Free.Pure(Some((hd,tl))) => Stepper.Emits(hd, go(stepf(tl)))
case Free.Fail(t) => Stepper.Fail(t)
case bound: Free.Bind[ReadSegment,_,UO] =>
val f = bound.asInstanceOf[Free.Bind[ReadSegment,Any,UO]].f
val fx = bound.fx.asInstanceOf[Free.Eval[ReadSegment,UO]].fr
Stepper.Await(segment => go(Free.Bind[ReadSegment,UO,UO](Free.Pure(fx(segment)), f)))
case e => sys.error("Free.ViewL structure must be Pure(a), Fail(e), or Bind(Eval(fx),k), was: " + e)
case FreeC.Pure(None) => Stepper.Done
case FreeC.Pure(Some((hd,tl))) => Stepper.Emits(hd, go(stepf(tl)))
case FreeC.Fail(t) => Stepper.Fail(t)
case bound: FreeC.Bind[ReadSegment,_,UO] =>
val f = bound.asInstanceOf[FreeC.Bind[ReadSegment,Any,UO]].f
val fx = bound.fx.asInstanceOf[FreeC.Eval[ReadSegment,UO]].fr
Stepper.Await(segment => go(FreeC.Bind[ReadSegment,UO,UO](FreeC.Pure(fx(segment)), f)))
case e => sys.error("FreeC.ViewL structure must be Pure(a), Fail(e), or Bind(Eval(fx),k), was: " + e)
}
}
go(stepf(p.covary[Read].apply(prompts)))
@@ -1,16 +1,16 @@
package fs2
import fs2.internal.Free
import fs2.internal.FreeC
object Pipe2 {
/** Creates a [[Stepper]], which allows incrementally stepping a pure `Pipe2`. */
def stepper[I,I2,O](p: Pipe2[Pure,I,I2,O]): Stepper[I,I2,O] = {
type ReadSegment[R] = Either[Option[Segment[I,Unit]] => R, Option[Segment[I2,Unit]] => R]
type Read[R] = Free[ReadSegment,R]
type Read[R] = FreeC[ReadSegment,R]
type UO = Option[(Segment[O,Unit],Stream[Read,O])]
def prompts[X](id: ReadSegment[Option[Segment[X,Unit]]]): Stream[Read,X] = {
Stream.eval[Read,Option[Segment[X,Unit]]](Free.Eval(id)).flatMap {
Stream.eval[Read,Option[Segment[X,Unit]]](FreeC.Eval(id)).flatMap {
case None => Stream.empty
case Some(segment) => Stream.segment(segment).append(prompts(id))
}
@@ -26,19 +26,19 @@ object Pipe2 {
def go(s: Read[UO]): Stepper[I,I2,O] = Stepper.Suspend { () =>
s.viewL.get match {
case Free.Pure(None) => Stepper.Done
case Free.Pure(Some((hd,tl))) => Stepper.Emits(hd, go(stepf(tl)))
case Free.Fail(t) => Stepper.Fail(t)
case bound: Free.Bind[ReadSegment,_,UO] =>
val f = bound.asInstanceOf[Free.Bind[ReadSegment,Any,UO]].f
val fx = bound.fx.asInstanceOf[Free.Eval[ReadSegment,UO]].fr
case FreeC.Pure(None) => Stepper.Done
case FreeC.Pure(Some((hd,tl))) => Stepper.Emits(hd, go(stepf(tl)))
case FreeC.Fail(t) => Stepper.Fail(t)
case bound: FreeC.Bind[ReadSegment,_,UO] =>
val f = bound.asInstanceOf[FreeC.Bind[ReadSegment,Any,UO]].f
val fx = bound.fx.asInstanceOf[FreeC.Eval[ReadSegment,UO]].fr
fx match {
case Left(recv) =>
Stepper.AwaitL(segment => go(Free.Bind[ReadSegment,UO,UO](Free.Pure(recv(segment)), f)))
Stepper.AwaitL(segment => go(FreeC.Bind[ReadSegment,UO,UO](FreeC.Pure(recv(segment)), f)))
case Right(recv) =>
Stepper.AwaitR(segment => go(Free.Bind[ReadSegment,UO,UO](Free.Pure(recv(segment)), f)))
Stepper.AwaitR(segment => go(FreeC.Bind[ReadSegment,UO,UO](FreeC.Pure(recv(segment)), f)))
}
case e => sys.error("Free.ViewL structure must be Pure(a), Fail(e), or Bind(Eval(fx),k), was: " + e)
case e => sys.error("FreeC.ViewL structure must be Pure(a), Fail(e), or Bind(Eval(fx),k), was: " + e)
}
}
go(stepf(p.covary[Read].apply(promptsL, promptsR)))
@@ -1,7 +1,7 @@
package fs2
import cats.effect.Sync
import fs2.internal.{ Algebra, Free }
import fs2.internal.{ Algebra, FreeC }
/**
* A `p: Pull[F,O,R]` reads values from one or more streams, returns a
@@ -25,19 +25,19 @@ import fs2.internal.{ Algebra, Free }
* @hideImplicitConversion PureOps
* @hideImplicitConversion covaryPure
*/
final class Pull[+F[_],+O,+R] private(private val free: Free[Algebra[Nothing,Nothing,?],R]) extends AnyVal {
final class Pull[+F[_],+O,+R] private(private val free: FreeC[Algebra[Nothing,Nothing,?],R]) extends AnyVal {
private[fs2] def get[F2[x]>:F[x],O2>:O,R2>:R]: Free[Algebra[F2,O2,?],R2] = free.asInstanceOf[Free[Algebra[F2,O2,?],R2]]
private[fs2] def get[F2[x]>:F[x],O2>:O,R2>:R]: FreeC[Algebra[F2,O2,?],R2] = free.asInstanceOf[FreeC[Algebra[F2,O2,?],R2]]
/** Alias for `_.map(_ => o2)`. */
def as[R2](r2: R2): Pull[F,O,R2] = map(_ => r2)
/** Returns a pull with the result wrapped in `Right`, or an error wrapped in `Left` if the pull has failed. */
def attempt: Pull[F,O,Either[Throwable,R]] =
Pull.fromFree(get[F,O,R].map(r => Right(r)).onError(t => Free.Pure(Left(t))))
Pull.fromFreeC(get[F,O,R].map(r => Right(r)).onError(t => FreeC.Pure(Left(t))))
/** Interpret this `Pull` to produce a `Stream`. The result type `R` is discarded. */
def stream: Stream[F,O] = Stream.fromFree(this.scope.get[F,O,R] map (_ => ()))
def stream: Stream[F,O] = Stream.fromFreeC(this.scope.get[F,O,R] map (_ => ()))
/** Lifts this pull to the specified output type. */
def covaryOutput[O2>:O]: Pull[F,O2,R] = this.asInstanceOf[Pull[F,O2,R]]
@@ -46,13 +46,13 @@ final class Pull[+F[_],+O,+R] private(private val free: Free[Algebra[Nothing,Not
def covaryResource[R2>:R]: Pull[F,O,R2] = this.asInstanceOf[Pull[F,O,R2]]
/** Applies the resource of this pull to `f` and returns the result in a new `Pull`. */
def map[R2](f: R => R2): Pull[F,O,R2] = Pull.fromFree(get map f)
def map[R2](f: R => R2): Pull[F,O,R2] = Pull.fromFreeC(get map f)
}
object Pull {
private[fs2] def fromFree[F[_],O,R](free: Free[Algebra[F,O,?],R]): Pull[F,O,R] =
new Pull(free.asInstanceOf[Free[Algebra[Nothing,Nothing,?],R]])
private[fs2] def fromFreeC[F[_],O,R](free: FreeC[Algebra[F,O,?],R]): Pull[F,O,R] =
new Pull(free.asInstanceOf[FreeC[Algebra[Nothing,Nothing,?],R]])
/** Result of `acquireCancellable`. */
sealed abstract class Cancellable[+F[_],+R] {
@@ -97,17 +97,17 @@ object Pull {
* instead of failing the pull.
*/
def attemptEval[F[_],R](fr: F[R]): Pull[F,Nothing,Either[Throwable,R]] =
fromFree(
fromFreeC(
Algebra.eval[F,Nothing,R](fr).
map(r => Right(r): Either[Throwable,R]).
onError(t => Algebra.pure[F,Nothing,Either[Throwable,R]](Left(t))))
/** The completed `Pull`. Reads and outputs nothing. */
val done: Pull[Nothing,Nothing,Unit] = fromFree[Nothing,Nothing,Unit](Algebra.pure[Nothing,Nothing,Unit](()))
val done: Pull[Nothing,Nothing,Unit] = fromFreeC[Nothing,Nothing,Unit](Algebra.pure[Nothing,Nothing,Unit](()))
/** Evaluates the supplied effectful value and returns the result as the resource of the returned pull. */
def eval[F[_],R](fr: F[R]): Pull[F,Nothing,R] =
fromFree(Algebra.eval[F,Nothing,R](fr))
fromFreeC(Algebra.eval[F,Nothing,R](fr))
/** Reads and outputs nothing, and fails with the given error. */
def fail(err: Throwable): Pull[Nothing,Nothing,Nothing] =
@@ -122,38 +122,38 @@ object Pull {
/** Ouptuts a single value. */
def output1[F[_],O](o: O): Pull[F,O,Unit] =
fromFree(Algebra.output1[F,O](o))
fromFreeC(Algebra.output1[F,O](o))
/** Ouptuts a segment of values. */
def output[F[_],O](os: Segment[O,Unit]): Pull[F,O,Unit] =
fromFree(Algebra.output[F,O](os))
fromFreeC(Algebra.output[F,O](os))
/** Pull that outputs nothing and has result of `r`. */
def pure[F[_],R](r: R): Pull[F,Nothing,R] =
fromFree(Algebra.pure(r))
fromFreeC(Algebra.pure(r))
/**
* Pull that outputs the specified segment and returns the result of the segment as the result
* of the pull. Less efficient than [[output]].
*/
def segment[F[_],O,R](s: Segment[O,R]): Pull[F,O,R] =
fromFree(Algebra.segment[F,O,R](s))
fromFreeC(Algebra.segment[F,O,R](s))
/**
* Returns a pull that evaluates the supplied by-name each time the pull is used,
* allowing use of a mutable value in pull computations.
*/
def suspend[F[_],O,R](p: => Pull[F,O,R]): Pull[F,O,R] =
fromFree(Algebra.suspend(p.get))
fromFreeC(Algebra.suspend(p.get))
private def release[F[_]](token: Algebra.Token): Pull[F,Nothing,Unit] =
fromFree[F,Nothing,Unit](Algebra.release(token))
fromFreeC[F,Nothing,Unit](Algebra.release(token))
/** Provides syntax for pulls that are invariant in `F`, `O`, and `R`. */
implicit def InvariantOps[F[_],O,R](p: Pull[F,O,R]): InvariantOps[F,O,R] = new InvariantOps(p.get)
/** Provides syntax for pulls that are invariant in `F`, `O`, and `R`. */
final class InvariantOps[F[_],O,R] private[Pull] (private val free: Free[Algebra[F,O,?],R]) extends AnyVal {
private def self: Pull[F,O,R] = Pull.fromFree(free)
final class InvariantOps[F[_],O,R] private[Pull] (private val free: FreeC[Algebra[F,O,?],R]) extends AnyVal {
private def self: Pull[F,O,R] = Pull.fromFreeC(free)
/** Lifts this pull to the specified effect type. */
def covary[F2[x]>:F[x]]: Pull[F2,O,R] = self.asInstanceOf[Pull[F2,O,R]]
@@ -163,7 +163,7 @@ object Pull {
/** Applies the resource of this pull to `f` and returns the result. */
def flatMap[O2>:O,R2](f: R => Pull[F,O2,R2]): Pull[F,O2,R2] =
Pull.fromFree(self.get[F,O2,R] flatMap { r => f(r).get })
Pull.fromFreeC(self.get[F,O2,R] flatMap { r => f(r).get })
/** Alias for `flatMap(_ => p2)`. */
def >>[O2>:O,R2](p2: => Pull[F,O2,R2]): Pull[F,O2,R2] =
@@ -175,17 +175,17 @@ object Pull {
/** If `this` terminates with `Pull.fail(e)`, invoke `h(e)`. */
def onError[O2>:O,R2>:R](h: Throwable => Pull[F,O2,R2]): Pull[F,O2,R2] =
Pull.fromFree(self.get[F,O2,R2] onError { e => h(e).get })
Pull.fromFreeC(self.get[F,O2,R2] onError { e => h(e).get })
/** Tracks any resources acquired during this pull and release them when the pull completes. */
def scope: Pull[F,O,R] = Pull.fromFree(Algebra.scope(free))
def scope: Pull[F,O,R] = Pull.fromFreeC(Algebra.scope(free))
}
/** Provides syntax for pure pulls. */
implicit def PureOps[O,R](p: Pull[Pure,O,R]): PureOps[O,R] = new PureOps(p.get[Pure,O,R])
/** Provides syntax for pure pulls. */
final class PureOps[O,R] private[Pull] (private val free: Free[Algebra[Pure,O,?],R]) extends AnyVal {
private def self: Pull[Pure,O,R] = Pull.fromFree[Pure,O,R](free)
final class PureOps[O,R] private[Pull] (private val free: FreeC[Algebra[Pure,O,?],R]) extends AnyVal {
private def self: Pull[Pure,O,R] = Pull.fromFreeC[Pure,O,R](free)
def covary[F[_]]: Pull[F,O,R] = self.asInstanceOf[Pull[F,O,R]]
def covaryAll[F[_],O2>:O,R2>:R]: Pull[F,O2,R2] = self.asInstanceOf[Pull[F,O2,R2]]
def flatMap[F[_],O2>:O,R2](f: R => Pull[F,O2,R2]): Pull[F,O2,R2] = covary[F].flatMap(f)
Oops, something went wrong.

0 comments on commit 31605b7

Please sign in to comment.