Skip to content

Commit

Permalink
Complete ch04
Browse files Browse the repository at this point in the history
  • Loading branch information
Abhijit Sarkar committed Dec 21, 2024
1 parent bc4c7f9 commit 72a9350
Show file tree
Hide file tree
Showing 4 changed files with 120 additions and 1 deletion.
5 changes: 4 additions & 1 deletion .scalafmt.conf
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,7 @@ version = "3.8.3"
align.preset = more
maxColumn = 120
runner.dialect = scala3
assumeStandardLibraryStripMargin = true
assumeStandardLibraryStripMargin = true
project.excludePaths = [
"glob:**/ch04/src/**.scala"
]
11 changes: 11 additions & 0 deletions ch04/src/Cat.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package ch04

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

object Cat:
given catDisplay: Display[Cat]:
def display(cat: Cat): String =
val name = Display.display(cat.name)
val age = Display.display(cat.age)
val color = Display.display(cat.color)
s"$name is a $age year-old $color cat."
23 changes: 23 additions & 0 deletions ch04/src/Display.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package ch04

trait Display[A]:
def display(value: A): String


object Display:
given stringDisplay: Display[String]:
def display(input: String): String = input

given intDisplay: Display[Int]:
def display(input: Int): String = input.toString

def display[A](input: A)(using p: Display[A]): String =
p.display(input)

def print[A](input: A)(using Display[A]): Unit =
println(display(input))

object DisplaySyntax:
extension [A](value: A)(using p: Display[A])
def display: String = p.display(value)
def print: Unit = Display.print(value)
82 changes: 82 additions & 0 deletions ch04/src/ch04.sc
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
import ch04.DisplaySyntax.*
import ch04.Display

/*
components that make up a type class:
- A trait, which is the type class
- Type class instances, which are given instances.
- Type class usage, which uses using clauses.
Type classes can be composed from components using type class composition.
We can view type classes as marrying codata with tools to select and compose implementations based on type.
We can also view type classes as shifting implementation from the definition site to the call site.
Finally, can see type classes as a mechanism for ad-hoc polymorphism,
allowing us to define common functionality for otherwise unrelated types.
*/
given Display[ch04.Cat] with
def display(cat: ch04.Cat): String =
val name = cat.name.display
val age = cat.age.display
val color = cat.color.display
s"$name is a $age year-old $color cat."

ch04.Cat("Garfield", 41, "ginger and black").display

trait Animal
trait Cat extends Animal
trait DomesticShorthair extends Cat

trait Inv[A]:
def result: String

object Inv:
given Inv[Cat] with
def result = "Invariant"

def apply[A](using instance: Inv[A]): String =
instance.result

trait Co[+A]:
def result: String

object Co:
given Co[Cat] with
def result = "Covariant"

def apply[A](using instance: Co[A]): String =
instance.result

trait Contra[-A]:
def result: String

object Contra:
given Contra[Cat] with
def result = "Contravariant"

def apply[A](using instance: Contra[A]): String =
instance.result

// Works!
Inv[Cat]
// res1: String = "Invariant"
Co[Animal]
// res2: String = "Covariant"
Co[Cat]
// res3: String = "Covariant"
Contra[DomesticShorthair]
// res4: String = "Contravariant"
Contra[Cat]
// res5: String = "Contravariant"

// Don't work!

// With invariance any type that is not Cat will fail.
// Inv[Animal]
// Inv[DomesticShorthair]

// Covariance fails for any subtype of the type for which the instance is declared.
// Co[DomesticShorthair]

// Contravariance fails for any supertype of the type for which the instance is declared.
// Contra[Animal]

0 comments on commit 72a9350

Please sign in to comment.