Skip to content

Commit

Permalink
1.4 MEET CATS
Browse files Browse the repository at this point in the history
1.5 Example Eq
1.6 Controlling Instance Selection
  • Loading branch information
Kicey committed Jan 19, 2024
1 parent 7f2dfab commit c0b3a4e
Show file tree
Hide file tree
Showing 13 changed files with 168 additions and 15 deletions.
3 changes: 2 additions & 1 deletion build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@ lazy val root = project
libraryDependencies ++= Seq(
"org.scalameta" %% "munit" % "0.7.29" % Test,
"org.scalactic" %% "scalactic" % "3.2.17",
"org.typelevel" %% "cats-core" % "2.10.0",
"org.scalatest" %% "scalatest" % "3.2.17" % "test",
"org.scalatest" %% "scalatest-flatspec" % "3.2.17" % "test"
"org.scalatest" %% "scalatest-flatspec" % "3.2.17" % "test",
)
)
6 changes: 6 additions & 0 deletions src/main/scala/_1_Theory/_4_MEET_CATS/CatsShow.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package _1_Theory._4_MEET_CATS

import cats.Show

val showInt: Show[Int] = Show[Int]
val showString: Show[String] = Show[String]
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package _1_Theory._4_MEET_CATS

import cats.Show

import java.util.Date

implicit val dateShow: Show[Date] =
(date: Date) => s"${date.getTime}ms since the epoch."
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package _1_Theory._6_Controlling_Instance_Selection

sealed trait A
final case object B extends A
final case object C extends A

trait Printer[-T]:
def print(t: T): Unit

object PrinterInstances:

implicit val aPrinter: Printer[A] = (t: A) => println(s"a printer print $t")

implicit val bPrinter: Printer[B.type] = (t: B.type) => println(s"b printer print $t")

// implicit val cPrinter: Printer[C.type] = (t: C.type) => println(s"c printer print $t")

object PrinterUse:
def print[T](t: T)(using printer: Printer[T]): Unit =
printer.print(t)
Original file line number Diff line number Diff line change
Expand Up @@ -3,28 +3,22 @@ package _1_Theory._3_Exercise_Printable_Library
import org.scalatest.flatspec.AnyFlatSpec



class PrintableUse extends AnyFlatSpec:

"cat" should "be printable with implicit instance" in:
final case class Cat(name: String, age: Int, color: String)

final case class Cat(name: String, age: Int, color: String)
given Printable[Cat] with
def format(cat: Cat) = s"${cat.name} is a ${cat.age} year-old ${cat.color} cat."

given Printable[Cat] with
def format(cat: Cat) = s"${cat.name} is a ${cat.age} year-old ${cat.color} cat."
"cat" should "be printable with implicit instance" in :

val cat = Cat("Garfield", 35, "orange and black")
assert(Printable.format(cat) == "Garfield is a 35 year-old orange and black cat.")
Printable.print(cat)

"cat" should "be printable with extension method" in:

final case class Cat(name: String, age: Int, color: String)
"cat" should "be printable with extension method" in :

import PrintableSyntax._
import PrintableSyntax._

given Printable[Cat] with
def format(cat: Cat) = s"${cat.name} is a ${cat.age} year-old ${cat.color} cat."

val cat = Cat("Garfield", 35, "orange and black")
cat.print
val cat = Cat("Garfield", 35, "orange and black")
cat.print
22 changes: 22 additions & 0 deletions src/test/scala/_1_Theory/_4_MEET_CATS/CatsShowTest.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package _1_Theory._4_MEET_CATS

import org.scalatest.flatspec.AnyFlatSpec

class CatsShowTest extends AnyFlatSpec:
"showInt.show(123)" should "create string '123'" in:
val intAsString = showInt.show(123)
assert(intAsString == "123")

"showString.show('abc')" should "create string 'abc'" in:
val stringAsString = showString.show("abc")
assert(stringAsString == "abc")

"123.show" should "create string '123'" in:
import cats.syntax.show._
val intAsString = 123.show
assert(intAsString == "123")

"abc.show" should "create string 'abc'" in:
import cats.syntax.show._
val stringAsString = "abc".show
assert(stringAsString == "abc")
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package _1_Theory._4_MEET_CATS

import org.scalatest.flatspec.AnyFlatSpec

class CustomShowInstancesTest extends AnyFlatSpec:

"new Date().show" should "return a string representation of the date" in:
import java.util.Date
import _1_Theory._4_MEET_CATS.dateShow
import cats.syntax.show._

val date = new Date()
assert(date.show == s"${date.getTime.toString}ms since the epoch.")
3 changes: 3 additions & 0 deletions src/test/scala/_1_Theory/_4_MEET_CATS/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
* Normally, we can simply import cats as:
* `import cats._` imports all of Cats’ type classes in one go;
* `import cats.implicits._` imports all of the standard type class in‐ stances and all of the syntax in one go.
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package _1_Theory._4_MEET_CATS._6_Exercise_Cat_Show

import org.scalatest.flatspec.AnyFlatSpec

class PrintableCatWithCats extends AnyFlatSpec:
final case class Cat(name: String, age: Int, color: String)

"PrintableCatWithCats" should "print cat" in:
import cats.Show
import cats.syntax.show._

implicit val catShow: Show[Cat] =
Show.show(cat => s"${cat.name} is a ${cat.age} year-old ${cat.color} cat.")

val cat = Cat("Garfield", 38, "ginger and black")
assert(cat.show == "Garfield is a 38 year-old ginger and black cat.")
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package _1_Theory._5_Example_Eq._5_Exercise_Equality_Liberty_and_Felinity

import cats.Eq
import org.scalatest.flatspec.AnyFlatSpec

class CatEqTest extends AnyFlatSpec:

final case class Cat(name: String, age: Int, color: String)

import cats.syntax.eq._
import cats.syntax.option._

val cat1: Cat = Cat("Garfield", 38, "orange and black")
val cat2: Cat = Cat("Garfield", 38, "orange and black")
val cat3: Cat = Cat("Heathcliff", 33, "orange and black")

implicit val catEq: Eq[Cat] = (cat1: Cat, cat2: Cat) =>
cat1.name == cat2.name
&& cat1.age == cat2.age
&& cat1.color == cat2.color

"CatEq" should "return true for equal cats" in:
assert(cat1 eqv cat2)

it should "return false for non-equal cats" in:
assert(cat1 =!= cat3)

it should "return true for equal cats with option" in:
val optCat1 = Option(cat1)
val optCat2 = Option(cat2)
assert(optCat1 eqv optCat2)
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package _1_Theory._6_Controlling_Instance_Selection

import org.scalatest.flatspec.AnyFlatSpec

class ContravariantTest extends AnyFlatSpec:

"contravariant" should "work fine on both issues on scala3" in:
import PrinterInstances._

// issue1:
PrinterUse.print(C)
// a printer print C

// issue2:
PrinterUse.print(B)
// b printer print B
Empty file.
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
* Covariance:
Covariance means that the type F[B] is a subtype of the type F[A] if B is a subtype of A. This is useful for modelling many types, including collections like List and Option:

```scala
trait List[+A]
trait Option[+A]
```

* Contravariance:
Perhaps confusingly, contravariance means that the type F[B] is a subtype of F[A] if A is a subtype of B.This is useful for modelling types that represent inputs, like our JsonWriter type class above:

```scala
trait JsonWriter[-A] {
def write(value: A): Json
}
```

* Invariance:
This means the types F[A] and F[B] are never subtypes of one another, no matter what the relationship between A and B. This is the default semantics for Scala type constructors.



* Pay Attention: The two issues arisen in this section can be achieved in scala3, see the test in the same folder.

0 comments on commit c0b3a4e

Please sign in to comment.