diff --git a/src/pages/applicatives/semigroupal.md b/src/pages/applicatives/semigroupal.md index 2c63b4a0..dbccd900 100644 --- a/src/pages/applicatives/semigroupal.md +++ b/src/pages/applicatives/semigroupal.md @@ -135,8 +135,9 @@ case class Cat(name: String, born: Int, color: String) ``` Internally `mapN` uses the `Semigroupal` -to extract the values from the `Option` -and the `Functor` to apply the values to the function. +to join all values into a single `Option` +and the `Functor` to sequence +the joined `Option` with supplied function. It's nice to see that this syntax is type checked. If we supply a function that diff --git a/src/pages/case-studies/validation/check.md b/src/pages/case-studies/validation/check.md index 01c04d2f..d1940d3e 100644 --- a/src/pages/case-studies/validation/check.md +++ b/src/pages/case-studies/validation/check.md @@ -145,9 +145,9 @@ final case class CheckF[E, A](func: A => Either[E, A]) { CheckF { a => (this(a), that(a)) match { case (Left(e1), Left(e2)) => (e1 |+| e2).asLeft - case (Left(e), Right(a)) => e.asLeft - case (Right(a), Left(e)) => e.asLeft - case (Right(a1), Right(a2)) => a.asRight + case (Left(e), Right(_)) => e.asLeft + case (Right(_), Left(e)) => e.asLeft + case (Right(_), Right(_)) => a.asRight } } } @@ -234,9 +234,9 @@ object wrapper { case And(left, right) => (left(a), right(a)) match { case (Left(e1), Left(e2)) => (e1 |+| e2).asLeft - case (Left(e), Right(a)) => e.asLeft - case (Right(a), Left(e)) => e.asLeft - case (Right(a1), Right(a2)) => a.asRight + case (Left(e), Right(_)) => e.asLeft + case (Right(_), Left(e)) => e.asLeft + case (Right(_), Right(_)) => a.asRight } } } @@ -298,7 +298,7 @@ is using the pattern for applicative functors. but it doesn't have the semantics we want. It fails fast instead of accumulating errors. -If we want to accumulate errors +If we want to accumulate errors, `Validated` is a more appropriate abstraction. As a bonus, we get more code reuse because we can lean on the applicative instance of `Validated` diff --git a/src/pages/case-studies/validation/index.md b/src/pages/case-studies/validation/index.md index 68a6bcd9..986122fe 100644 --- a/src/pages/case-studies/validation/index.md +++ b/src/pages/case-studies/validation/index.md @@ -18,7 +18,7 @@ the types of checks we want to perform: - A user must be over 18 years old or must have parental consent. -- A `String` ID must be parsable as a `Int` +- A `String` ID must be parsable as an `Int` and the `Int` must correspond to a valid record ID. - A bid in an auction must apply diff --git a/src/pages/monad-transformers/index.md b/src/pages/monad-transformers/index.md index 563fd686..d32cb60d 100644 --- a/src/pages/monad-transformers/index.md +++ b/src/pages/monad-transformers/index.md @@ -627,7 +627,7 @@ def tacticalReport(ally1: String, ally2: String): String =
We use the `value` method to unpack the monad stack -and `Await` and `fold` to unpack the `Future` and `Either`: +and `Await` to unpack the `Future` and `Either`: ```tut:book:silent import scala.concurrent.Await diff --git a/src/pages/monad-transformers/summary.md b/src/pages/monad-transformers/summary.md index 43f25d2b..a474909d 100644 --- a/src/pages/monad-transformers/summary.md +++ b/src/pages/monad-transformers/summary.md @@ -18,7 +18,7 @@ when writing transformer types for deeply nested monads. With this look at monad transformers, we have now covered everything we need to know about monads and the sequencing of computations using `flatMap`. -In the next chapter we will switch tack +In the next chapter we will switch track and discuss two new type classes, `Semigroupal` and `Applicative`, that support new kinds of operation such as `zipping` independent values within a context. diff --git a/src/pages/monads/writer.md b/src/pages/monads/writer.md index 6f4d15ba..4fb643ae 100644 --- a/src/pages/monads/writer.md +++ b/src/pages/monads/writer.md @@ -6,11 +6,11 @@ We can use it to record messages, errors, or additional data about a computation, and extract the log alongside the final result. -One common use for `Writers` is +One common use for `Writer` is recording sequences of steps in multi-threaded computations where standard imperative logging techniques can result in interleaved messages from different contexts. -With `Writer` the log for the computation is tied to the result, +With `Writer`, the log for the computation is tied to the result, so we can run concurrent computations without mixing logs.
@@ -60,7 +60,7 @@ so we can read types like `WriterT[Id, W, A]` as `Writer[W, A]`: type Writer[W, A] = WriterT[Id, W, A] ``` -For convenience, Cats provides a way of creating `Writers` +For convenience, Cats provides a way of creating `Writer` specifying only the log or the result. If we only have a result we can use the standard `pure` syntax. To do this we must have a `Monoid[W]` in scope