Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
3cae48c
fix typo: Nexted → Nested
fabianhjr Feb 11, 2023
24aedd3
sbt: 1.6.1 → 1.8.2
fabianhjr Feb 11, 2023
ba0a40f
scala: 2.13.8 → 3.2.2
fabianhjr Feb 11, 2023
39aeddf
cats: 2.7.0 → 2.9.0
fabianhjr Feb 11, 2023
f5916ec
Substitute Scala 2 Typelevel's Kind Projector Plugin with Scala 3
fabianhjr Feb 11, 2023
1b79221
sbt-mdoc: 2.3.0 → 2.3.7
fabianhjr Feb 11, 2023
17006e3
Upgrade overhaul: fix errors/warnings after upgrades
fabianhjr Feb 11, 2023
4d1c8f8
Fix Pandoc Deprecation of --self-contained; use --embed-resources --s…
fabianhjr Feb 11, 2023
5871a96
implicit val/implicit param → given/using
fabianhjr Feb 11, 2023
95f483c
implicit def → given
fabianhjr Feb 11, 2023
e503659
implicit class → extension
fabianhjr Feb 11, 2023
2096d33
Overhaul some text regarding implicits
fabianhjr Feb 11, 2023
b220a4b
remove typelevel catalysts since it was deprecated in 2019
fabianhjr Feb 11, 2023
9bfe988
sealed trait/case [class|object] → enum
fabianhjr Feb 11, 2023
f638e77
Scala 3 overhaul to 2.6
fabianhjr Feb 11, 2023
ad913a0
Scala 3 overhaul to 3.1
fabianhjr Feb 11, 2023
5be7e9a
Scala 3 overhaul to 3.2
fabianhjr Feb 11, 2023
d69e5a4
Scala 3 overhaul to 3.3
fabianhjr Feb 11, 2023
0308dc6
Scala 3 overhaul to 3.4
fabianhjr Feb 11, 2023
24e9f33
Scala 3 overhaul to 3.5
fabianhjr Feb 11, 2023
31c2f7c
Scala 3 overhaul to 3.6
fabianhjr Feb 11, 2023
ca04554
Scala 3 overhaul to 4.x
fabianhjr Feb 12, 2023
dd793d0
coffeescript: 2.5.1 → 2.7.0 via yarn upgradeInteractive
fabianhjr Feb 12, 2023
e9a9fe0
import `._` → `.*`
fabianhjr Feb 12, 2023
9f32cc6
Scala 3 overhaul to 5.x
fabianhjr Feb 12, 2023
75330d5
Scala 3 Braceless Syntax cont.
fabianhjr Feb 12, 2023
e8fdd1b
Scala 3 Braceless Syntax cont.
fabianhjr Feb 12, 2023
3a34ced
Address some implicit → given/using changes
fabianhjr Feb 12, 2023
34e4b76
Preface Scala 3 tweak
fabianhjr Feb 12, 2023
fb80a9c
That does work due to package
fabianhjr Feb 12, 2023
1fa5dec
what-is-fp: adjust code
fabianhjr Feb 18, 2023
3847a8c
anatomy: further refactor implicit to contextual abstractions
fabianhjr Feb 18, 2023
c14b942
implicits: refactor implicits
fabianhjr Feb 18, 2023
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
11 changes: 7 additions & 4 deletions build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ ThisBuild / name := "scala-with-cats"
ThisBuild / organization := "com.scalawithcats"
ThisBuild / version := "0.0.1"

ThisBuild / scalaVersion := "2.13.8"
ThisBuild / scalaVersion := "3.2.2"

ThisBuild / useSuperShell := false
Global / logLevel := Level.Warn
Expand All @@ -14,11 +14,14 @@ enablePlugins(MdocPlugin)
mdocIn := sourceDirectory.value / "pages"
mdocOut := target.value / "pages"

val catsVersion = "2.7.0"
scalacOptions ++= Seq(
"-explain", // Better diagnostics
"-Ykind-projector:underscores" // In-lieu of kind-projector
)

libraryDependencies ++= Seq("org.typelevel" %% "cats-core" % catsVersion)
val catsVersion = "2.9.0"

addCompilerPlugin("org.typelevel" % "kind-projector" % "0.13.2" cross CrossVersion.full)
libraryDependencies ++= Seq("org.typelevel" %% "cats-core" % catsVersion)

mdocVariables := Map(
"SCALA_VERSION" -> scalaVersion.value,
Expand Down
6 changes: 3 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,12 @@
"devDependencies": {
"bootstrap": "^3.4.1",
"coffeeify": "1.0.0",
"coffeescript": "^2.5.1",
"jquery": "3.5.0",
"uglifyify": "2.6.0",
"lessc": "^1.0.2",
"underscore": "1.7.0",
"pandoc-filter": "0.1.6",
"coffeescript": "^2.5.1"
"uglifyify": "2.6.0",
"underscore": "1.7.0"
},
"author": "Noel Welsh and Dave Gurnell"
}
2 changes: 1 addition & 1 deletion project/Pandoc.scala
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ object Pandoc {
"--table-of-contents",
"--highlight-style tango",
"--standalone",
"--self-contained",
"--embed-resources",
),
extras,
metadata,
Expand Down
2 changes: 1 addition & 1 deletion project/build.properties
Original file line number Diff line number Diff line change
@@ -1 +1 @@
sbt.version=1.6.1
sbt.version=1.8.2
2 changes: 1 addition & 1 deletion project/plugins.sbt
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
addSbtPlugin("org.scalameta" % "sbt-mdoc" % "2.3.0" )
addSbtPlugin("org.scalameta" % "sbt-mdoc" % "2.3.7" )
// addSbtPlugin("io.github.davidgregory084" % "sbt-tpolecat" % "0.1.10")
11 changes: 4 additions & 7 deletions src/pages/adt/scala.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,8 @@ Not everyone makes their case classes `final`, but they should. A non-`final` ca
A logical or (a sum type) is represented by an `enum`. For the sum type `A` is a `B` **or** `C` the Scala 3 representation is

```scala
enum A {
case B
case C
}
enum A:
case B, C
```

There are a few wrinkles to be aware of.
Expand All @@ -37,13 +35,12 @@ If we have a sum of products, such as:
the representation is

```scala
enum A {
enum A:
case B(d: D, e: E)
case C(f: F, g: G)
}
```

In other words you can't write `final case class` inside an `enum`. You also can't nest `enum` inside `enum`. Nexted logical ors can be rewritten into a single logical or containing only logical ands (known as disjunctive normal form) so this is not a limitation in practice. However the Scala 2 representation is still available in Scala 3 should you want more expressivity.
In other words you can't write `final case class` inside an `enum`. You also can't nest `enum` inside `enum`. Nested logical ors can be rewritten into a single logical or containing only logical ands (known as disjunctive normal form) so this is not a limitation in practice. However the Scala 2 representation is still available in Scala 3 should you want more expressivity.


### Algebraic Data Types in Scala 2
Expand Down
6 changes: 2 additions & 4 deletions src/pages/applicatives/applicative.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,16 +24,14 @@ introduced in Chapter [@sec:monads].
Here's a simplified definition in code:

```scala
trait Apply[F[_]] extends Semigroupal[F] with Functor[F] {
trait Apply[F[_]] extends Semigroupal[F] with Functor[F]:
def ap[A, B](ff: F[A => B])(fa: F[A]): F[B]

def product[A, B](fa: F[A], fb: F[B]): F[(A, B)] =
ap(map(fa)(a => (b: B) => (a, b)))(fb)
}

trait Applicative[F[_]] extends Apply[F] {
trait Applicative[F[_]] extends Apply[F]:
def pure[A](a: A): F[A]
}
```

Breaking this down, the `ap` method applies a parameter `fa`
Expand Down
26 changes: 13 additions & 13 deletions src/pages/applicatives/examples.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@ provide parallel as opposed to sequential execution:

```scala mdoc:silent
import cats.Semigroupal
import cats.instances.future._ // for Semigroupal
import scala.concurrent._
import scala.concurrent.duration._
import cats.instances.future.* // for Semigroupal
import scala.concurrent.*
import scala.concurrent.duration.*
import scala.concurrent.ExecutionContext.Implicits.global

val futurePair = Semigroupal[Future].
Expand All @@ -31,7 +31,7 @@ by the time we call `product`.
We can use apply syntax to zip fixed numbers of `Futures`:

```scala mdoc:silent
import cats.syntax.apply._ // for mapN
import cats.syntax.apply.* // for mapN

case class Cat(
name: String,
Expand Down Expand Up @@ -59,7 +59,7 @@ but we actually get the cartesian product of their elements:

```scala mdoc:silent
import cats.Semigroupal
import cats.instances.list._ // for Semigroupal
import cats.instances.list.* // for Semigroupal
```

```scala mdoc
Expand All @@ -81,7 +81,7 @@ we find that `product` implements
the same fail-fast behaviour as `flatMap`:

```scala mdoc:silent
import cats.instances.either._ // for Semigroupal
import cats.instances.either.* // for Semigroupal

type ErrorOr[A] = Either[Vector[String], A]
```
Expand All @@ -105,8 +105,8 @@ If we have a monad we can implement `product` as follows.

```scala mdoc:silent
import cats.Monad
import cats.syntax.functor._ // for map
import cats.syntax.flatMap._ // for flatmap
import cats.syntax.functor.* // for map
import cats.syntax.flatMap.* // for flatmap

def product[F[_]: Monad, A, B](fa: F[A], fb: F[B]): F[(A,B)] =
fa.flatMap(a =>
Expand Down Expand Up @@ -178,8 +178,8 @@ the definition of `product` in terms of
import cats.Monad
```
```scala mdoc:silent
import cats.syntax.functor._ // for map
import cats.syntax.flatMap._ // for flatMap
import cats.syntax.functor.* // for map
import cats.syntax.flatMap.* // for flatMap

def product[F[_]: Monad, A, B](x: F[A], y: F[B]): F[(A, B)] =
x.flatMap(a => y.map(b => (a, b)))
Expand All @@ -189,8 +189,8 @@ This code is equivalent to a for comprehension:

```scala mdoc:invisible:reset-object
import cats.Monad
import cats.syntax.flatMap._ // for flatMap
import cats.syntax.functor._ // for map
import cats.syntax.flatMap.* // for flatMap
import cats.syntax.functor.* // for map
```
```scala mdoc:silent
def product[F[_]: Monad, A, B](x: F[A], y: F[B]): F[(A, B)] =
Expand All @@ -204,7 +204,7 @@ The semantics of `flatMap` are what give rise
to the behaviour for `List` and `Either`:

```scala mdoc:silent
import cats.instances.list._ // for Semigroupal
import cats.instances.list.* // for Semigroupal
```

```scala mdoc
Expand Down
2 changes: 1 addition & 1 deletion src/pages/applicatives/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ fails on the first call to `parseInt`
and doesn't go any further:

```scala mdoc:silent
import cats.syntax.either._ // for catchOnly
import cats.syntax.either.* // for catchOnly

def parseInt(str: String): Either[String, Int] =
Either.catchOnly[NumberFormatException](str.toInt).
Expand Down
21 changes: 9 additions & 12 deletions src/pages/applicatives/parallel.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ stops at the first error.

```scala mdoc:silent
import cats.Semigroupal
import cats.instances.either._ // for Semigroupal
import cats.instances.either.* // for Semigroupal

type ErrorOr[A] = Either[Vector[String], A]
val error1: ErrorOr[Int] = Left(Vector("Error 1"))
Expand All @@ -33,8 +33,8 @@ using `tupled`
as a short-cut.

```scala mdoc:silent
import cats.syntax.apply._ // for tupled
import cats.instances.vector._ // for Semigroup on Vector
import cats.syntax.apply.* // for tupled
import cats.instances.vector.* // for Semigroup on Vector
```
```scala mdoc
(error1, error2).tupled
Expand All @@ -45,7 +45,7 @@ we simply replace `tupled` with its "parallel" version
called `parTupled`.

```scala mdoc:silent
import cats.syntax.parallel._ // for parTupled
import cats.syntax.parallel.* // for parTupled
```
```scala mdoc
(error1, error2).parTupled
Expand All @@ -57,7 +57,7 @@ Any type that has a `Semigroup` instance will work.
For example, here we use `List` instead.

```scala mdoc:silent
import cats.instances.list._ // for Semigroup on List
import cats.instances.list.* // for Semigroup on List

type ErrorOrList[A] = Either[List[String], A]
val errStr1: ErrorOrList[Int] = Left(List("error 1"))
Expand Down Expand Up @@ -88,13 +88,12 @@ Let's dig into how `Parallel` works.
The definition below is the core of `Parallel`.

```scala
trait Parallel[M[_]] {
trait Parallel[M[_]]:
type F[_]

def applicative: Applicative[F]
def monad: Monad[M]
def parallel: ~>[M, F]
}
```

This tells us if there is a `Parallel` instance for some type constructor `M` then:
Expand All @@ -115,13 +114,11 @@ by defining a `FunctionK` that converts an `Option` to a `List`.
```scala mdoc:silent
import cats.arrow.FunctionK

object optionToList extends FunctionK[Option, List] {
object optionToList extends FunctionK[Option, List]:
def apply[A](fa: Option[A]): List[A] =
fa match {
fa match
case None => List.empty[A]
case Some(a) => List(a)
}
}
```
```scala mdoc
optionToList(Some(1))
Expand Down Expand Up @@ -160,7 +157,7 @@ insted of creating the cartesian product.
We can see by writing a little bit of code.

```scala mdoc:silent
import cats.instances.list._
import cats.instances.list.*
```
```scala mdoc
(List(1, 2), List(3, 4)).tupled
Expand Down
25 changes: 12 additions & 13 deletions src/pages/applicatives/semigroupal.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,8 @@ a `Semigroupal[F]` allows us to combine them to form an `F[(A, B)]`.
Its definition in Cats is:

```scala
trait Semigroupal[F[_]] {
trait Semigroupal[F[_]]:
def product[A, B](fa: F[A], fb: F[B]): F[(A, B)]
}
```

As we discussed at the beginning of this chapter,
Expand All @@ -34,7 +33,7 @@ Let's join some `Options` as an example:

```scala mdoc:silent:reset-object
import cats.Semigroupal
import cats.instances.option._ // for Semigroupal
import cats.instances.option.* // for Semigroupal
```

```scala mdoc
Expand All @@ -59,7 +58,7 @@ For example, the methods `tuple2` through `tuple22`
generalise `product` to different arities:

```scala mdoc:silent
import cats.instances.option._ // for Semigroupal
import cats.instances.option.* // for Semigroupal
```

```scala mdoc
Expand Down Expand Up @@ -98,8 +97,8 @@ We import the syntax from [`cats.syntax.apply`][cats.syntax.apply].
Here's an example:

```scala mdoc:silent
import cats.instances.option._ // for Semigroupal
import cats.syntax.apply._ // for tupled and mapN
import cats.instances.option.* // for Semigroupal
import cats.syntax.apply.* // for tupled and mapN
```

The `tupled` method is implicitly added to the tuple of `Options`.
Expand Down Expand Up @@ -167,11 +166,11 @@ Here's an example:

```scala mdoc:silent:reset-object
import cats.Monoid
import cats.instances.int._ // for Monoid
import cats.instances.invariant._ // for Semigroupal
import cats.instances.list._ // for Monoid
import cats.instances.string._ // for Monoid
import cats.syntax.apply._ // for imapN
import cats.instances.int.* // for Monoid
import cats.instances.invariant.* // for Semigroupal
import cats.instances.list.* // for Monoid
import cats.instances.string.* // for Monoid
import cats.syntax.apply.* // for imapN

final case class Cat(
name: String,
Expand All @@ -185,7 +184,7 @@ val tupleToCat: (String, Int, List[String]) => Cat =
val catToTuple: Cat => (String, Int, List[String]) =
cat => (cat.name, cat.yearOfBirth, cat.favoriteFoods)

implicit val catMonoid: Monoid[Cat] = (
given catMonoid: Monoid[Cat] = (
Monoid[String],
Monoid[Int],
Monoid[List[String]]
Expand All @@ -196,7 +195,7 @@ Our `Monoid` allows us to create "empty" `Cats`,
and add `Cats` together using the syntax from Chapter [@sec:monoids]:

```scala mdoc:silent
import cats.syntax.semigroup._ // for |+|
import cats.syntax.semigroup.* // for |+|

val garfield = Cat("Garfield", 1978, List("Lasagne"))
val heathcliff = Cat("Heathcliff", 1988, List("Junk Food"))
Expand Down
Loading