Skip to content

Commit

Permalink
Add asError, reorder combinators
Browse files Browse the repository at this point in the history
  • Loading branch information
ioleo committed Aug 6, 2019
1 parent 3682d61 commit 05a66dc
Show file tree
Hide file tree
Showing 9 changed files with 114 additions and 65 deletions.
19 changes: 14 additions & 5 deletions core/shared/src/main/scala/zio/Exit.scala
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,20 @@ sealed trait Exit[+E, +A] extends Product with Serializable { self =>
*/
final def <*>[E1 >: E, B](that: Exit[E1, B]): Exit[E1, (A, B)] = zipWith(that)((_, _), _ ++ _)

/**
* Replaces the success value with the one provided.
*/
final def as[B](b: B): Exit[E, B] = map(_ => b)

/**
* Replaces the error value with the one provided.
*/
final def asError[E1](e1: E1): Exit[E1, A] =
self match {
case e @ Success(_) => e
case Failure(c) => halt(c.map(_ => e1))
}

/**
* Maps over both the error and value type.
*/
Expand All @@ -61,11 +75,6 @@ sealed trait Exit[+E, +A] extends Product with Serializable { self =>
@deprecated("use as", "1.0.0")
final def const[B](b: B): Exit[E, B] = as(b)

/**
* Replaces the value with the one provided.
*/
final def as[B](b: B): Exit[E, B] = map(_ => b)

/**
* Flat maps over the value type.
*/
Expand Down
6 changes: 3 additions & 3 deletions core/shared/src/main/scala/zio/Runtime.scala
Original file line number Diff line number Diff line change
Expand Up @@ -110,14 +110,14 @@ trait Runtime[+R] {
final def unsafeRunToFuture[E <: Throwable, A](io: ZIO[R, E, A]): scala.concurrent.Future[A] =
unsafeRun(io.toFuture)

@deprecated("use as", "1.0.0")
final def const[R1](r1: R1): Runtime[R1] = as(r1)

/**
* Constructs a new `Runtime` with the specified new environment.
*/
final def as[R1](r1: R1): Runtime[R1] = map(_ => r1)

@deprecated("use as", "1.0.0")
final def const[R1](r1: R1): Runtime[R1] = as(r1)

/**
* Constructs a new `Runtime` with the specified executor.
*/
Expand Down
21 changes: 10 additions & 11 deletions core/shared/src/main/scala/zio/ZIO.scala
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,16 @@ sealed trait ZIO[-R, +E, +A] extends Serializable { self =>
final def andThen[R1 >: A, E1 >: E, B](that: ZIO[R1, E1, B]): ZIO[R, E1, B] =
self >>> that

/**
* Maps the success value of this effect to the specified constant value.
*/
final def as[B](b: B): ZIO[R, E, B] = self.flatMap(new ZIO.ConstFn(() => b))

/**
* Maps the error value of this effect to the specified constant value.
*/
final def asError[E1](e1: E1): ZIO[R, E1, A] = mapError(_ => e1)

/**
* Returns an effect whose failure and success channels have been mapped by
* the specified pair of functions, `f` and `g`.
Expand Down Expand Up @@ -467,11 +477,6 @@ sealed trait ZIO[-R, +E, +A] extends Serializable { self =>
*/
def map[B](f: A => B): ZIO[R, E, B] = new ZIO.FlatMap(self, new ZIO.MapFn(f))

/**
* Returns an effect whose success is replaced by the specified `b` value.
*/
final def as[B](b: B): ZIO[R, E, B] = self.flatMap(new ZIO.ConstFn(() => b))

/**
* Returns an effect with its error channel mapped using the specified
* function. This can be used to lift a "smaller" error into a "larger"
Expand All @@ -480,12 +485,6 @@ sealed trait ZIO[-R, +E, +A] extends Serializable { self =>
final def mapError[E2](f: E => E2): ZIO[R, E2, A] =
self.foldCauseM(new ZIO.MapErrorFn(f), new ZIO.SucceedFn(f))

/**
* Returns an effect whose error channel is replaced by the specified `e2` error.
* This can be used to lift a "smaller" error into a "larger" error.
*/
final def asError[E2](e2: E2): ZIO[R, E2, A] = mapError(_ => e2)

/**
* Returns an effect with its full cause of failure mapped using the
* specified function. This can be used to transform errors while
Expand Down
2 changes: 1 addition & 1 deletion core/shared/src/main/scala/zio/ZManaged.scala
Original file line number Diff line number Diff line change
Expand Up @@ -619,7 +619,7 @@ final case class ZManaged[-R, +E, +A](reserve: ZIO[R, E, Reservation[R, E, A]])
* Return unit while running the effect
*/
lazy final val unit: ZManaged[R, E, Unit] =
const(())
as(())

/**
* The inverse operation `ZManaged.sandboxed`
Expand Down
10 changes: 5 additions & 5 deletions core/shared/src/main/scala/zio/ZSchedule.scala
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,11 @@ trait ZSchedule[-R, -A, +B] extends Serializable { self =>
}
}

/**
* Returns a new schedule that maps this schedule to a constant output.
*/
final def as[C](c: => C): ZSchedule[R, A, C] = map(_ => c)

/**
* A named alias for `&&`.
*/
Expand Down Expand Up @@ -235,11 +240,6 @@ trait ZSchedule[-R, -A, +B] extends Serializable { self =>
@deprecated("use as", "1.0.0")
final def const[C](c: => C): ZSchedule[R, A, C] = as(c)

/**
* Returns a new schedule that maps this schedule to a constant output.
*/
final def as[C](c: => C): ZSchedule[R, A, C] = map(_ => c)

/**
* Returns a new schedule that deals with a narrower class of inputs than
* this schedule.
Expand Down
15 changes: 10 additions & 5 deletions core/shared/src/main/scala/zio/stm/STM.scala
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,16 @@ final class STM[+E, +A] private[stm] (
final def >>=[E1 >: E, B](f: A => STM[E1, B]): STM[E1, B] =
self flatMap f

/**
* Maps the success value of this effect to the specified constant value.
*/
final def as[B](b: => B): STM[E, B] = self map (_ => b)

/**
* Maps the error value of this effect to the specified constant value.
*/
final def asError[E1](e: => E1): STM[E1, A] = self mapError (_ => e)

/**
* Simultaneously filters and maps the value produced by this effect.
*/
Expand All @@ -124,11 +134,6 @@ final class STM[+E, +A] private[stm] (
@deprecated("use as", "1.0.0")
final def const[B](b: => B): STM[E, B] = as(b)

/**
* Maps the success value of this effect to the specified constant value.
*/
final def as[B](b: => B): STM[E, B] = self map (_ => b)

/**
* Converts the failure channel into an `Either`.
*/
Expand Down
74 changes: 47 additions & 27 deletions streams-tests/jvm/src/test/scala/zio/stream/SinkSpec.scala
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,17 @@ class SinkSpec(implicit ee: org.specs2.concurrent.ExecutionEnv)

def is = "SinkSpec".title ^ s2"""
Combinators
as
happy path $asHappyPath
init error $asInitError
step error $asStepError
extract error $asExtractError

asError
init error $asErrorInitError
step error $asErrorStepError
extract error $asErrorExtractError

chunked
happy path $chunkedHappyPath
empty $chunkedEmpty
Expand Down Expand Up @@ -48,12 +59,6 @@ class SinkSpec(implicit ee: org.specs2.concurrent.ExecutionEnv)
step error $contramapMStepError
extract error $contramapMExtractError

as
happy path $asHappyPath
init error $asInitError
step error $asStepError
extract error $asExtractError

dimap
happy path $dimapHappyPath
init error $dimapInitError
Expand Down Expand Up @@ -175,7 +180,7 @@ class SinkSpec(implicit ee: org.specs2.concurrent.ExecutionEnv)

Constructors
foldLeft $foldLeft

fold $fold
short circuits $foldShortCircuits

Expand Down Expand Up @@ -245,6 +250,41 @@ class SinkSpec(implicit ee: org.specs2.concurrent.ExecutionEnv)
result <- sink.extract(Step.state(step))
} yield result

private def asHappyPath = {
val sink = ZSink.identity[Int].as("const")
unsafeRun(sinkIteration(sink, 1).map(_ must_=== "const"))
}

private def asInitError = {
val sink = initErrorSink.as("const")
unsafeRun(sinkIteration(sink, 1).either.map(_ must_=== Left("Ouch")))
}

private def asStepError = {
val sink = stepErrorSink.as("const")
unsafeRun(sinkIteration(sink, 1).either.map(_ must_=== Left("Ouch")))
}

private def asErrorInitError = {
val sink = initErrorSink.asError("Error")
unsafeRun(sinkIteration(sink, 1).either.map(_ must_=== Left("Error")))
}

private def asErrorStepError = {
val sink = stepErrorSink.asError("Error")
unsafeRun(sinkIteration(sink, 1).either.map(_ must_=== Left("Error")))
}

private def asErrorExtractError = {
val sink = extractErrorSink.asError("Error")
unsafeRun(sinkIteration(sink, 1).either.map(_ must_=== Left("Error")))
}

private def asExtractError = {
val sink = extractErrorSink.as("const")
unsafeRun(sinkIteration(sink, 1).either.map(_ must_=== Left("Ouch")))
}

private def chunkedHappyPath = {
val sink = ZSink.collectAll[Int].chunked
unsafeRun(sinkIteration(sink, Chunk(1, 2, 3, 4, 5)).map(_ must_=== List(1, 2, 3, 4, 5)))
Expand Down Expand Up @@ -345,26 +385,6 @@ class SinkSpec(implicit ee: org.specs2.concurrent.ExecutionEnv)
unsafeRun(sinkIteration(sink, "1").either.map(_ must_=== Left("Ouch")))
}

private def asHappyPath = {
val sink = ZSink.identity[Int].as("const")
unsafeRun(sinkIteration(sink, 1).map(_ must_=== "const"))
}

private def asInitError = {
val sink = initErrorSink.as("const")
unsafeRun(sinkIteration(sink, 1).either.map(_ must_=== Left("Ouch")))
}

private def asStepError = {
val sink = stepErrorSink.as("const")
unsafeRun(sinkIteration(sink, 1).either.map(_ must_=== Left("Ouch")))
}

private def asExtractError = {
val sink = extractErrorSink.as("const")
unsafeRun(sinkIteration(sink, 1).either.map(_ must_=== Left("Ouch")))
}

private def dimapHappyPath = {
val sink = ZSink.identity[Int].dimap[String, String](_.toInt)(_.toString.reverse)
unsafeRun(sinkIteration(sink, "123").map(_ must_=== "321"))
Expand Down
26 changes: 21 additions & 5 deletions streams/shared/src/main/scala/zio/stream/ZSink.scala
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,27 @@ trait ZSink[-R, +E, +A0, -A, +B] { self =>
)(implicit ev: A00 =:= A1): ZSink[R1, E1, A00, A1, (B, C)] =
zip(that)

/**
* Creates a sink that always produces `c`
*/
final def as[C](c: => C): ZSink[R, E, A0, A, C] = self.map(_ => c)

/**
* Replaces any error produced by this sink.
*/
final def asError[E1](e1: E1): ZSink[R, E1, A0, A, B] =
new ZSink[R, E1, A0, A, B] {
type State = self.State

val initial = self.initial.asError(e1)

def step(state: State, a: A): ZIO[R, E1, Step[State, A0]] =
self.step(state, a).asError(e1)

def extract(state: State): ZIO[R, E1, B] =
self.extract(state).asError(e1)
}

/**
* Takes a `Sink`, and lifts it to be chunked in its input. This
* will not improve performance, but can be used to adapt non-chunked sinks
Expand Down Expand Up @@ -266,11 +287,6 @@ trait ZSink[-R, +E, +A0, -A, +B] { self =>
@deprecated("use as", "1.0.0")
final def const[C](c: => C): ZSink[R, E, A0, A, C] = as(c)

/**
* Creates a sink that always produces `c`
*/
final def as[C](c: => C): ZSink[R, E, A0, A, C] = self.map(_ => c)

/**
* Creates a sink that transforms entering values with `f` and
* outgoing values with `g`
Expand Down
6 changes: 3 additions & 3 deletions test/shared/src/main/scala/zio/test/Assertion.scala
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,14 @@ package zio.test
sealed trait Assertion[+A] { self =>
import Assertion._

@deprecated("use as", "1.0.0")
final def const[L2](l2: L2): Assertion[L2] = as(l2)

/**
* Returns a new result, with the message mapped to the specified constant.
*/
final def as[L2](l2: L2): Assertion[L2] = self.map(_ => l2)

@deprecated("use as", "1.0.0")
final def const[L2](l2: L2): Assertion[L2] = as(l2)

/**
* Combines this result with the specified result.
*/
Expand Down

0 comments on commit 05a66dc

Please sign in to comment.