Skip to content

Commit 2962b2e

Browse files
author
Dean Wampler
committed
More refinements based on Seth's feedback, through chapter 19.
1 parent 433a07a commit 2962b2e

File tree

8 files changed

+73
-71
lines changed

8 files changed

+73
-71
lines changed

src/main/scala/progscala3/basicoop/Abstract.scala

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,15 @@
33
package progscala3.basicoop
44

55
enum LoggingLevel: // <1>
6-
case INFO, WARN, ERROR
6+
case Info, Warn, Error
77

88
trait Logging:
99
import LoggingLevel.*
10-
final def info(message: String): Unit = log(INFO, message)
11-
final def warn(message: String): Unit = log(WARN, message)
12-
final def error(message: String): Unit = log(ERROR, message)
10+
final def info(message: String): Unit = log(Info, message)
11+
final def warn(message: String): Unit = log(Warn, message)
12+
final def error(message: String): Unit = log(Error, message)
1313
final def log(level: LoggingLevel, message: String): Unit =
14-
write(s"$level: $message")
14+
write(s"${level.toString.toUpperCase}: $message")
1515

1616
protected val write: String => Unit // <2>
1717

src/main/scala/progscala3/fp/categories/MapMerge.scala

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@
22
package progscala3.fp.categories
33
import progscala3.contexts.typeclass.Monoid
44

5-
given MapMergeMonoid[K,V : Monoid]: Monoid[Map[K,V]] with // <1>
6-
def unit: Map[K,V] = Map.empty
7-
extension (map1: Map[K,V]) def combine(map2: Map[K,V]): Map[K,V] =
5+
given MapMergeMonoid[K, V : Monoid]: Monoid[Map[K, V]] with // <1>
6+
def unit: Map[K, V] = Map.empty
7+
extension (map1: Map[K, V]) def combine(map2: Map[K, V]): Map[K, V] =
88
val kmon = summon[Monoid[V]]
99
(map1.keySet union map2.keySet).map { k =>
1010
val v1 = map1.getOrElse(k, kmon.unit)
Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
// tag::definition[]
12
// src/main/scala/progscala3/fp/categories/Monad.scala
23
package progscala3.fp.categories
34
import scala.annotation.targetName
@@ -6,13 +7,6 @@ trait Monad[M[_]]: // <1>
67
def flatMap[A, B](fa: M[A])(f: A => M[B]): M[B] // <2>
78
def unit[A](a: => A): M[A] // <3>
89

9-
// Some common aliases:
10-
def bind[A,B](fa: M[A])(f: A => M[B]): M[B] = flatMap(fa)(f) // <4>
11-
@targetName("rocket")
12-
def >>=[A,B](fa: M[A])(f: A => M[B]): M[B] = flatMap(fa)(f)
13-
def pure[A](a: => A): M[A] = unit(a)
14-
def `return`[A](a: => A): M[A] = unit(a) // backticks to avoid keyword
15-
1610
object SeqM extends Monad[Seq]:
1711
def flatMap[A, B](seq: Seq[A])(f: A => Seq[B]): Seq[B] =
1812
seq flatMap f
@@ -22,4 +16,13 @@ object OptionM extends Monad[Option]:
2216
def flatMap[A, B](opt: Option[A])(f: A => Option[B]):Option[B]=
2317
opt flatMap f
2418
def unit[A](a: => A): Option[A] = Option(a)
19+
// end::definition[]
2520

21+
// Some common aliases for the methods that you'll see in some math texbooks
22+
// and other languages, like Haskell. (This part is not shown in the book).
23+
trait MonadPlus[M[_]] extends Monad[M]:
24+
def bind[A,B](fa: M[A])(f: A => M[B]): M[B] = flatMap(fa)(f) // <4>
25+
@targetName("rocket")
26+
def >>=[A,B](fa: M[A])(f: A => M[B]): M[B] = flatMap(fa)(f)
27+
def pure[A](a: => A): M[A] = unit(a)
28+
def `return`[A](a: => A): M[A] = unit(a) // backticks to avoid keyword

src/main/scala/progscala3/fp/datastructs/FoldLeftRight.scala

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ import scala.annotation.tailrec
77
* Simplified implementations of foldLeft and foldRight.
88
*/
99
object FoldLeftRight:
10-
1110
def foldLeft[A,B](s: Seq[A])(seed: B)(f: (B,A) => B): B =
1211
@tailrec
1312
def fl(accum: B, s2: Seq[A]): B = s2 match

src/main/scala/progscala3/traits/Abstract2.scala

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,17 @@
22
package progscala3.traits
33

44
enum LoggingLevel: // <1>
5-
case INFO, WARN, ERROR
5+
case Info, Warn, Error
66

7-
trait Logging(name: String): // <2>
7+
trait Logging(name: String):
88
import LoggingLevel.*
9-
def info(message: String): Unit = log(INFO, message)
10-
def warn(message: String): Unit = log(WARN, message)
11-
def error(message: String): Unit = log(ERROR, message)
12-
def log(level: LoggingLevel, message: String): Unit =
13-
_log(s"$level ($name): $message") // <3>
9+
final def info(message: String): Unit = log(Info, message)
10+
final def warn(message: String): Unit = log(Warn, message)
11+
final def error(message: String): Unit = log(Error, message)
12+
final def log(level: LoggingLevel, message: String): Unit =
13+
_log(s"${level.toString.toUpperCase} ($name): $message") // <2>
1414

15-
protected val _log: String => Unit // <4>
15+
protected val _log: String => Unit // <3>
1616

1717
trait ConsoleLogging extends Logging:
18-
protected val _log = println // <5>
18+
protected val _log = println // <4>

src/main/scala/progscala3/traits/Logging.scala

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,14 @@
22
package progscala3.traits.logging
33

44
enum LoggingLevel:
5-
case DEBUG, INFO, WARN, ERROR, FATAL // <1>
5+
case Debug, Info, Warn, Error, Fatal // <1>
66

77
trait Logger(val level: LoggingLevel): // <2>
88
def log(message: String): Unit
99

1010
trait ConsoleLogger extends Logger:
11-
def log(message: String): Unit = println(s"$level: $message")
11+
def log(message: String): Unit =
12+
println(s"${level.toString.toUpperCase}: $message")
1213

1314
class Service(val name: String, level: LoggingLevel) // <3>
1415
extends ConsoleLogger with Logger(level)

src/script/scala/progscala3/rounding/Traits.scala

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ val service1 = new Service("one")
1111

1212
// tag::logging[]
1313
enum Level: // <1>
14-
case INFO, WARNING, ERROR
14+
case Info, Warn, Error
1515
def ==(other: Level): Boolean = this.ordinal == other.ordinal
1616
def >=(other: Level): Boolean = this.ordinal >= other.ordinal
1717

@@ -22,15 +22,15 @@ trait Logging:
2222
def log(level: Level, message: String): Unit
2323

2424
final def info(message: String): Unit = // <3>
25-
if level >= INFO then log(INFO, message)
26-
final def warning(message: String): Unit =
27-
if level >= WARNING then log(WARNING, message)
25+
if level >= Info then log(Info, message)
26+
final def warn(message: String): Unit =
27+
if level >= Warn then log(Warn, message)
2828
final def error(message: String): Unit =
29-
if level >= ERROR then log(ERROR, message)
29+
if level >= Error then log(Error, message)
3030

3131
trait StdoutLogging extends Logging: // <4>
3232
def log(level: Level, message: String) =
33-
println(s"$level: $message")
33+
println(s"${level.toString.toUpperCase}: $message")
3434
// end::logging[]
3535

3636
// tag::example[]
@@ -42,6 +42,6 @@ case class LoggedService(name: String, level: Level)
4242
info(s"Ending work: result = $result")
4343
result
4444

45-
val service2 = LoggedService("two", Level.INFO)
45+
val service2 = LoggedService("two", Level.Info)
4646
(1 to 3) foreach (i => println(s"Result: ${service2.work(i)}"))
4747
// end::example[]

src/script/scala/progscala3/typesystem/intersectionunion/Union.scala

Lines changed: 36 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ case class Good(i: Int)
77
val error = Bad("Failed!")
88
val result = Good(0)
99

10-
val seq1 = Seq(error, result) // Inferred type: Seq[Object]!
10+
val seq1 = Seq(error, result) // Inferred type: Seq[AnyRef] or Seq[Object]!
1111
val seq: Seq[Good | Bad] = Seq(error, result)
1212
// end::declarations[]
1313

@@ -19,57 +19,56 @@ def process(result: Good | Bad): String = result match
1919
case Bad(message) => message
2020
case Good(value) => s"Success! value = $value"
2121

22-
val results: Seq[Good | Bad] = Seq(0, 1).map(work)
22+
val results = Seq(0, 1).map(work)
2323
val strings = results.map(process)
2424
// end::usage[]
2525

2626
// tag::distributive[]
27-
trait T1; trait T2; trait T3
27+
trait A; trait B; trait C
2828

29-
summon[(T1 & (T2 | T3)) =:= ((T1 & T2) | (T1 & T3))]
30-
summon[(T1 | (T2 & T3)) =:= ((T1 | T2) & (T1 | T3))]
29+
summon[(A & (B | C)) =:= ((A & B) | (A & C))]
30+
summon[(A | (B & C)) =:= ((A | B) & (A | C))]
3131

32-
val x1: T1 & (T2 | T3) = new T1 with T2 {}
33-
val x2: T1 & (T2 | T3) = new T1 with T3 {}
34-
val x3: T1 & (T2 | T3) = new T1 with T2 with T3 {}
35-
val x4: (T1 & T2) | (T1 & T3) = new T1 with T2 {}
36-
val x5: (T1 & T2) | (T1 & T3) = new T1 with T3 {}
37-
val x6: (T1 & T2) | (T1 & T3) = new T1 with T2 with T3 {}
38-
39-
val x7: T1 | (T2 & T3) = new T1 {}
40-
val x8: T1 | (T2 & T3) = new T2 with T3 {}
41-
val x9: T1 | (T2 & T3) = new T1 with T2 with T3 {}
42-
val x10: (T1 | T2) & (T1 | T3) = new T1 {}
43-
val x11: (T1 | T2) & (T1 | T3) = new T2 with T3 {}
44-
val x12: (T1 | T2) & (T1 | T3) = new T1 with T2 with T3 {}
32+
val x1: A & (B | C) = new A with B {}
33+
val x2: A & (B | C) = new A with C {}
34+
val x3: A & (B | C) = new A with B with C {}
35+
val x4: (A & B) | (A & C) = new A with B {}
36+
val x5: (A & B) | (A & C) = new A with C {}
37+
val x6: (A & B) | (A & C) = new A with B with C {}
4538

39+
val x7: A | (B & C) = new A {}
40+
val x8: A | (B & C) = new B with C {}
41+
val x9: A | (B & C) = new A with B with C {}
42+
val x10: (A | B) & (A | C) = new A {}
43+
val x11: (A | B) & (A | C) = new B with C {}
44+
val x12: (A | B) & (A | C) = new A with B with C {}
4645
// end::distributive[]
4746

4847
// tag::covariance[]
49-
val t123s: Seq[T1 | T2 | T3] = Seq(new T1 {}, new T2 {}, new T3 {})
50-
val t1s: Seq[T1] = t123s // ERROR
51-
val t2s: Seq[T2] = t123s // ERROR
52-
val t3s: Seq[T3] = t123s // ERROR
48+
val tABCs: Seq[A | B | C] = Seq(new A {}, new B {}, new C {})
49+
val tAs: Seq[A] = tABCs // ERROR
50+
val tBs: Seq[B] = tABCs // ERROR
51+
val tCs: Seq[C] = tABCs // ERROR
5352
// end::covariance[]
5453

5554
// tag::contravariance[]
56-
val seq1s: Seq[T1] = Seq(new T1 {})
57-
val seq2s: Seq[T2] = Seq(new T2 {})
58-
val seq3s: Seq[T3] = Seq(new T3 {})
59-
val seq123s1: Seq[T1 | T2 | T3] = seq1s
60-
val seq123s2: Seq[T1 | T2 | T3] = seq2s
61-
val seq123s3: Seq[T1 | T2 | T3] = seq3s
55+
val seqAs: Seq[A] = Seq(new A {})
56+
val seqBs: Seq[B] = Seq(new B {})
57+
val seqCs: Seq[C] = Seq(new C {})
58+
val seqABCs1: Seq[A | B | C] = seqAs
59+
val seqABCs2: Seq[A | B | C] = seqBs
60+
val seqABCs3: Seq[A | B | C] = seqCs
6261
// end::contravariance[]
6362

6463
// tag::contravariantfunctions[]
65-
val f123a: (T1 | T2 | T3) => String = _ match
66-
case t1: T1 => "T1"
67-
case t2: T2 => "T2"
68-
case t3: T3 => "T3"
69-
val f123b: (T1 => String) & (T2 => String) & (T3 => String) = f123a
70-
val f123c: (T1 & T2 & T3 => String) = f123a
64+
val fABC1: (A | B | C) => String = _ match
65+
case t1: A => "A"
66+
case t2: B => "B"
67+
case t3: C => "C"
68+
val fABC2: (A => String) & (B => String) & (C => String) = fABC1
7169

72-
val seqTs: Seq[T1 | T2 | T3] = Seq(new T1 {}, new T2 {}, new T3 {})
73-
seqTs.map(f123a)
74-
seqTs.map(f123b)
70+
val seqABCs: Seq[A | B | C] = Seq(new A {}, new B {}, new C {})
71+
seqABCs.map(fABC1)
72+
seqABCs.map(fABC2)
73+
seqABCs.map((x: AnyRef) => s"<$x>")
7574
// end::contravariantfunctions[]

0 commit comments

Comments
 (0)