Download - Real world gobbledygook
![Page 1: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/1.jpg)
Real-World Gobbledygook
What is all the fuss with all those monoids and semigroups I keep hearing about?
![Page 2: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/2.jpg)
Scala?
![Page 3: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/3.jpg)
public class MyClass {
private String someField;
public MyClass(String someField) {
this.someField = someField;
}
public String someField() {
return someField;
}
public String concat(String me) {
return someField + me;
}
public String hasCode() { .. }
public Boolean equals(Object obj) { .. }
}
![Page 4: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/4.jpg)
public class MyClass {
private String someField;
public MyClass(String someField) {
this.someField = someField;
}
public String someField() {
return someField;
}
public String concat(String me) {
return someField + me;
}
public String hasCode() { .. }
public Boolean equals(Object obj) { .. }
}
![Page 5: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/5.jpg)
class MyClass {
private String someField;
public MyClass(String someField) {
this.someField = someField;
}
String someField() {
return someField;
}
String concat(String me) {
return someField + me;
}
String hasCode() { .. }
Boolean equals(Object obj) { .. }
}
![Page 6: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/6.jpg)
class MyClass {
private String someField;
public MyClass(String someField) {
this.someField = someField;
}
String someField() {
return someField;
}
String concat(String me) {
return someField + me;
}
String hasCode() { .. }
Boolean equals(Object obj) { .. }
}
![Page 7: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/7.jpg)
class MyClass {
private someField: String;
public MyClass(someField: String) {
this.someField = someField;
}
String someField() {
return someField;
}
String concat(me: SomeField) {
return someField + me;
}
String hasCode() { .. }
Boolean equals(me: Object) { .. }
}
![Page 8: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/8.jpg)
class MyClass {
private someField: String;
public MyClass(someField: String) {
this.someField = someField;
}
String someField() {
return someField;
}
String concat(me: SomeField) {
return someField + me;
}
String hasCode() { .. }
Boolean equals(me: Object) { .. }
}
![Page 9: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/9.jpg)
class MyClass {
private someField: String;
public MyClass(someField: String) {
this.someField = someField;
}
String someField() {
return someField;
}
String concat(me: SomeField) {
return someField + me;
}
String hasCode() { .. }
Boolean equals(me: Object) { .. }
}
![Page 10: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/10.jpg)
class MyClass {
private someField: String;
public MyClass(someField: String) {
this.someField = someField;
}
def someField(): String = {
return someField;
}
def concat(me: SomeField): String = {
return someField + me;
}
def hasCode(): String = { .. }
def equals(me: Object): Boolean = { .. }
}
![Page 11: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/11.jpg)
class MyClass {
private someField: String;
public MyClass(someField: String) {
this.someField = someField;
}
def someField(): String = {
return someField;
}
def concat(me: SomeField): String = {
return someField + me;
}
def hasCode(): String = { .. }
def equals(me: Object): Boolean = { .. }
}
![Page 12: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/12.jpg)
class MyClass {
private someField: String;
public MyClass(someField: String) {
this.someField = someField;
}
def someField(): String = {
return someField;
}
def concat(me: SomeField): String = {
return someField + me;
}
def hasCode(): String = { .. }
def equals(me: Object): Boolean = { .. }
}
![Page 13: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/13.jpg)
class MyClass {
private someField: String;
public MyClass(someField: String) {
this.someField = someField;
}
def someField(): String = {
someField;
}
def concat(me: SomeField): String = {
someField + me;
}
def hasCode(): String = { .. }
def equals(me: Object): Boolean = { .. }
}
![Page 14: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/14.jpg)
class MyClass {
private someField: String;
public MyClass(someField: String) {
this.someField = someField;
}
def someField(): String = {
someField;
}
def concat(me: SomeField): String = {
someField + me;
}
def hasCode(): String = { .. }
def equals(me: Object): Boolean = { .. }
}
![Page 15: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/15.jpg)
class MyClass {
private someField: String;
public MyClass(someField: String) {
this.someField = someField;
}
def someField(): String = someField;
def concat(me: SomeField): String = someField + me;
def hasCode(): String = { .. }
def equals(me: Object): Boolean = { .. }
}
![Page 16: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/16.jpg)
class MyClass {
private someField: String;
public MyClass(someField: String) {
this.someField = someField;
}
def someField(): String = someField;
def concat(me: SomeField): String = someField + me;
def hasCode(): String = { .. }
def equals(me: Object): Boolean = { .. }
}
![Page 17: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/17.jpg)
class MyClass {
private someField: String
public MyClass(someField: String) {
this.someField = someField
}
def someField(): String = someField
def concat(me: SomeField): String = someField + me
def hasCode(): String = { .. }
def equals(me: Object): Boolean = { .. }
}
![Page 18: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/18.jpg)
class MyClass {
private someField: String
public MyClass(someField: String) {
this.someField = someField
}
def someField(): String = someField
def concat(me: SomeField): String = someField + me
def hasCode(): String = { .. }
def equals(me: Object): Boolean = { .. }
}
![Page 19: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/19.jpg)
class MyClass(someField: String) {
def someField(): String = someField
def concat(me: SomeField): String = someField + me
def hasCode(): String = { .. }
def equals(me: Object): Boolean = { .. }
}
![Page 20: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/20.jpg)
class MyClass(someField: String) {
def someField(): String = someField
def concat(me: SomeField): String = someField + me
def hasCode(): String = { .. }
def equals(me: Object): Boolean = { .. }
}
![Page 21: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/21.jpg)
class MyClass(val someField: String) {
def concat(me: SomeField): String = someField + me
def hasCode(): String = { .. }
def equals(me: Object): Boolean = { .. }
}
![Page 22: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/22.jpg)
class MyClass(val someField: String) {
def concat(me: SomeField): String = someField + me
def hasCode(): String = { .. }
def equals(me: Object): Boolean = { .. }
}
![Page 23: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/23.jpg)
class MyClass(val someField: String) {
def concat(me: SomeField): String = someField + me
def hasCode(): String = { .. }
def equals(me: Object): Boolean = { .. }
}
![Page 24: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/24.jpg)
case class MyClass(someField: String) {
def concat(me: SomeField): String = someField + me
}
![Page 25: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/25.jpg)
case class MyClass(someField: String) {
def concat(me: SomeField): String = someField + me
}
![Page 26: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/26.jpg)
Real-World Gobbledygook
What is all the fuss with all those monoids and semigroups I keep hearing about?
![Page 27: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/27.jpg)
“But what if I don’t care about Functional Programming?”
![Page 28: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/28.jpg)
“Functional Programming is merely an academic phenomenon.
![Page 29: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/29.jpg)
Why not FP?
![Page 30: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/30.jpg)
Why not FP?
● FP might be good nice academic exercise, but ..
![Page 31: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/31.jpg)
Why not FP?
● FP might be good nice academic exercise, but ..● .. has nothing to do with real world
![Page 32: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/32.jpg)
Why not FP?
● FP might be good nice academic exercise, but ..● .. has nothing to do with real world● The last three decades proved that OO-programming is
useful & necessary
![Page 33: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/33.jpg)
Why not FP?
● FP might be good nice academic exercise, but ..● .. has nothing to do with real world● The last three decades proved that OO-programming is
useful & necessary ● OO has some inconveniences, but it is a de facto standard
![Page 34: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/34.jpg)
Why not FP?
● FP might be good nice academic exercise, but ..● .. has nothing to do with real world● The last three decades proved that OO-programming is
useful & necessary ● OO has some inconveniences, but it is a de facto standard● FP is complex, I don’t understand it, I doubt it will be
applicable to real world, ever!
![Page 35: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/35.jpg)
![Page 36: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/36.jpg)
Edsger Dijkstra
![Page 37: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/37.jpg)
Edsger Dijkstraˈɛtsxər ˈdɛɪkstra
![Page 38: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/38.jpg)
Edsger Dijkstraˈɛtsxər ˈdɛɪkstra
https://en.wikipedia.org/wiki/Edsger_W._Dijkstra
![Page 39: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/39.jpg)
![Page 40: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/40.jpg)
![Page 41: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/41.jpg)
![Page 42: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/42.jpg)
![Page 43: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/43.jpg)
![Page 45: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/45.jpg)
![Page 46: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/46.jpg)
![Page 47: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/47.jpg)
This paper tries to convince us that the well-known goto statement should be eliminated from our programming languages or, at least (since I don’t think that it will ever be eliminated), that programmers should not use it. (...)
![Page 48: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/48.jpg)
This paper tries to convince us that the well-known goto statement should be eliminated from our programming languages or, at least (since I don’t think that it will ever be eliminated), that programmers should not use it. (...) The author is a proponent of the socalled “structured programming” style, in which, if I get it right, gotos are replaced by indentation.
![Page 49: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/49.jpg)
This paper tries to convince us that the well-known goto statement should be eliminated from our programming languages or, at least (since I don’t think that it will ever be eliminated), that programmers should not use it. (...) The author is a proponent of the socalled “structured programming” style, in which, if I get it right, gotos are replaced by indentation. Structured programming is a nice academic exercise, which works well for small examples, but I doubt that any real-world program will ever be written in such a style.
![Page 50: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/50.jpg)
This paper tries to convince us that the well-known goto statement should be eliminated from our programming languages or, at least (since I don’t think that it will ever be eliminated), that programmers should not use it. (...) The author is a proponent of the socalled “structured programming” style, in which, if I get it right, gotos are replaced by indentation. Structured programming is a nice academic exercise, which works well for small examples, but I doubt that any real-world program will ever be written in such a style. More than 10 years of industrial experience with Fortran have proved conclusively to everybody concerned that, in the real world, the goto is useful and necessary:
![Page 51: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/51.jpg)
This paper tries to convince us that the well-known goto statement should be eliminated from our programming languages or, at least (since I don’t think that it will ever be eliminated), that programmers should not use it. (...) The author is a proponent of the socalled “structured programming” style, in which, if I get it right, gotos are replaced by indentation. Structured programming is a nice academic exercise, which works well for small examples, but I doubt that any real-world program will ever be written in such a style. More than 10 years of industrial experience with Fortran have proved conclusively to everybody concerned that, in the real world, the goto is useful and necessary: its presence might cause some inconveniences in debugging, but it is a de facto standard and we must live with it.
![Page 52: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/52.jpg)
This paper tries to convince us that the well-known goto statement should be eliminated from our programming languages or, at least (since I don’t think that it will ever be eliminated), that programmers should not use it. (...) The author is a proponent of the socalled “structured programming” style, in which, if I get it right, gotos are replaced by indentation. Structured programming is a nice academic exercise, which works well for small examples, but I doubt that any real-world program will ever be written in such a style. More than 10 years of industrial experience with Fortran have proved conclusively to everybody concerned that, in the real world, the goto is useful and necessary: its presence might cause some inconveniences in debugging, but it is a de facto standard and we must live with it. It will take more than the academic elucubrations of a purist to remove it from our languages. (...)
![Page 53: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/53.jpg)
![Page 54: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/54.jpg)
“The Story of a Blackout”
In 5 acts
![Page 55: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/55.jpg)
Act.1: “Loss & Grief”
![Page 56: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/56.jpg)
![Page 57: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/57.jpg)
Our goal:
● DRY principle● Separation of concerns● Epic decoupling● Clean API● Minimal Boilerplate
![Page 58: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/58.jpg)
![Page 59: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/59.jpg)
![Page 60: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/60.jpg)
![Page 61: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/61.jpg)
![Page 62: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/62.jpg)
503 Service Temporarily Unavailablenginx
![Page 63: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/63.jpg)
503 Service Temporarily Unavailablenginx
![Page 64: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/64.jpg)
![Page 65: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/65.jpg)
![Page 66: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/66.jpg)
The 5 Stages of Loss and Grief
![Page 67: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/67.jpg)
The 5 Stages of Loss and Grief
1. Denial
![Page 68: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/68.jpg)
The 5 Stages of Loss and Grief
1. Denial2. Anger
![Page 69: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/69.jpg)
The 5 Stages of Loss and Grief
1. Denial2. Anger3. Bargaining
![Page 70: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/70.jpg)
The 5 Stages of Loss and Grief
1. Denial2. Anger3. Bargaining4. Depression
![Page 71: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/71.jpg)
The 5 Stages of Loss and Grief
1. Denial2. Anger3. Bargaining4. Depression5. Acceptance
![Page 72: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/72.jpg)
![Page 73: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/73.jpg)
Act.2: “The Mess”
![Page 74: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/74.jpg)
auction
![Page 75: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/75.jpg)
auctionify
![Page 76: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/76.jpg)
auctionify.io
![Page 77: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/77.jpg)
Domain & Feature RequestsDomain:
● Users place Orders in the auction system
Order
![Page 78: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/78.jpg)
Domain & Feature RequestsDomain:
● Users place Orders in the auction system● Orders can be:
○ General - contain list of Products○ Complex - combined from two or more
other Orders○ Cancelled - used to be fully fledged
Orders, but now are cancelled
Order
General Complex Cancelled
![Page 79: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/79.jpg)
Domain & Feature RequestsDomain:
● Users place Orders in the auction system● Orders can be:
○ General - contain list of Products○ Complex - combined from two or more
other Orders○ Cancelled - used to be fully fledged
Orders, but now are cancelled● Products can be:
○ Basic - id & price○ Discounted - wrapped Product &
discount○ OutOfStock - used to be in warehouse, but
now gone (sorry)
Order
General Complex Cancelled
Product
Basic Discounter Out of Stock
![Page 80: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/80.jpg)
Domain & Feature RequestsFeature Requests:
● Present current state of orders (JSON)● Calculate final checkout● Calculate average Order price● “Simplify” Orders
![Page 81: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/81.jpg)
Domain & Feature RequestsFeature Requests:
● Present current state of orders (JSON)● Calculate final checkout● Calculate average Order price● “Simplify” Orders
![Page 82: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/82.jpg)
sealed trait Order
case class GeneralOrder(products: List[Product]) extends Order
case object CancelledOrder extends Order
case class ComplexOrder(orders: List[Order]) extends Order
sealed trait Product
case class BasicProduct(id: Int, price: BigDecimal) extends Product
case class DiscountedProduct(product: Product,
discount: Double) extends Product
case object OutOfStock extends Product
![Page 83: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/83.jpg)
test("should evaluate order") {
val o1 = GeneralOrder(BasicProduct(10, BigDecimal("10.2")) :: Nil)
val o2 = GeneralOrder(DiscountedProduct(
product = BasicProduct(11, BigDecimal("1")),
discount = 0.2) :: Nil)
val o3 = CancelledOrder
val order = ComplexOrder(o1 :: o2 :: o3 :: Nil)
order.evaluate should equal (BigDecimal("11.0"))
}
![Page 84: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/84.jpg)
test("should evaluate order") {
val o1 = GeneralOrder(BasicProduct(10, BigDecimal("10.2")) :: Nil)
val o2 = GeneralOrder(DiscountedProduct(
product = BasicProduct(11, BigDecimal("1")),
discount = 0.2) :: Nil)
val o3 = CancelledOrder
val order = ComplexOrder(o1 :: o2 :: o3 :: Nil)
order.evaluate should equal (BigDecimal("11.0"))
}
[error] OrderTest.scala evaluate is not a member of jw.ComplexOrder
[error] order.evaluate should equal (BigDecimal("11.0"))
[error] ^
[error] one error found
![Page 85: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/85.jpg)
![Page 86: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/86.jpg)
![Page 87: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/87.jpg)
![Page 88: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/88.jpg)
![Page 89: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/89.jpg)
![Page 90: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/90.jpg)
![Page 91: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/91.jpg)
Subtype Polymorphism
![Page 92: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/92.jpg)
test("should evaluate order") {
val o1 = GeneralOrder(BasicProduct(10, BigDecimal("10.2")) :: Nil)
val o2 = GeneralOrder(DiscountedProduct(
product = BasicProduct(11, BigDecimal("1")),
discount = 0.2) :: Nil)
val o3 = CancelledOrder
val order = ComplexOrder(o1 :: o2 :: o3 :: Nil)
order.evaluate should equal (BigDecimal("11.0"))
}
[error] OrderTest.scala evaluate is not a member of jw.ComplexOrder
[error] order.evaluate should equal (BigDecimal("11.0"))
[error] ^
[error] one error found
![Page 93: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/93.jpg)
test("should evaluate order") {
val o1 = GeneralOrder(BasicProduct(10, BigDecimal("10.2")) :: Nil)
val o2 = GeneralOrder(DiscountedProduct(
product = BasicProduct(11, BigDecimal("1")),
discount = 0.2) :: Nil)
val o3 = CancelledOrder
val order = ComplexOrder(o1 :: o2 :: o3 :: Nil)
order.evaluate should equal (BigDecimal("11.0"))
}
![Page 94: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/94.jpg)
sealed trait Order
case class GeneralOrder(products: List[Product]) extends Order
case object CancelledOrder extends Order
case class ComplexOrder(orders: List[Order]) extends Order
sealed trait Product
case class BasicProduct(id: Int, price: BigDecimal) extends Product
case class DiscountedProduct(product: Product,
discount: Double) extends Product
case object OutOfStock extends Product
![Page 95: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/95.jpg)
trait Evaluatable[T] { def evaluate: T }
sealed trait Order extends Evaluatable[BigDecimal]
case object CancelledOrder extends Order {
def evaluate: BigDecimal = BigDecimal("0.0")
}
case class ComplexOrder(orders: List[Order]) extends Order {
def evaluate: BigDecimal = orders.foldLeft(BigDecimal("0.0")) {
case (acc, o) => acc + o.evaluate
}
}
case class GeneralOrder(products: List[Product]) extends Order {
def evaluate: BigDecimal = products.foldLeft(BigDecimal("0.0")) {
case (acc, p) => acc + p.evaluate
}
}
![Page 96: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/96.jpg)
trait Evaluatable[T] { def evaluate: T }
sealed trait Product extends Evaluatable[BigDecimal]
case class BasicProduct(id: Int, price: BigDecimal) extends Product {
def evaluate: BigDecimal = price
}
case class DiscountedProduct(product: Product, discount: Double) extends Product {
def evaluate: BigDecimal = product.evaluate * (1 - discount)
}
case object OutOfStock extends Product {
def evaluate: BigDecimal = BigDecimal("0.0")
}
![Page 97: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/97.jpg)
test("should evaluate order") {
val o1 = GeneralOrder(BasicProduct(10, BigDecimal("10.2")) :: Nil)
val o2 = GeneralOrder(DiscountedProduct(
product = BasicProduct(11, BigDecimal("1")),
discount = 0.2) :: Nil)
val o3 = CancelledOrder
val order = ComplexOrder(o1 :: o2 :: o3 :: Nil)
order.evaluate should equal (BigDecimal("11.0"))
}
![Page 98: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/98.jpg)
test("should evaluate order") {
val o1 = GeneralOrder(BasicProduct(10, BigDecimal("10.2")) :: Nil)
val o2 = GeneralOrder(DiscountedProduct(
product = BasicProduct(11, BigDecimal("1")),
discount = 0.2) :: Nil)
val o3 = CancelledOrder
val order = ComplexOrder(o1 :: o2 :: o3 :: Nil)
order.evaluate should equal (BigDecimal("11.0"))
}
[info] OrderTest:
[info] - should evaluate order
![Page 99: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/99.jpg)
![Page 100: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/100.jpg)
Domain & Feature RequestsFeature Requests:
● Present current state of orders (JSON)● Calculate final checkout● Calculate average Order price● “Simplify” Orders
![Page 101: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/101.jpg)
Domain & Feature RequestsFeature Requests:
● Present current state of orders (JSON)● Calculate final checkout● Calculate average Order price● “Simplify” Orders
![Page 102: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/102.jpg)
Domain & Feature RequestsFeature Requests:
● Present current state of orders (JSON)● Calculate final checkout● Calculate average Order price● “Simplify” Orders
![Page 103: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/103.jpg)
test("should calculate average") {
val o1 = GeneralOrder(DiscountedProduct(product =
BasicProduct(11, BigDecimal("1")), discount = 0.2) :: Nil)
val o2 = GeneralOrder(BasicProduct(10, BigDecimal("4")) :: Nil)
val o3 = GeneralOrder(BasicProduct(10, BigDecimal("10.2")) :: Nil)
Order.average(o1 :: o2 :: o3 :: Nil) should equal(BigDecimal("5.0"))
}
![Page 104: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/104.jpg)
test("should calculate average") {
val o1 = GeneralOrder(DiscountedProduct(product =
BasicProduct(11, BigDecimal("1")), discount = 0.2) :: Nil)
val o2 = GeneralOrder(BasicProduct(10, BigDecimal("4")) :: Nil)
val o3 = GeneralOrder(BasicProduct(10, BigDecimal("10.2")) :: Nil)
Order.average(o1 :: o2 :: o3 :: Nil) should equal(BigDecimal("5.0"))
}
[error] OrderTest.scala average is not a member of jw.Order
[error] Order.average should equal (BigDecimal("5.0"))
[error] ^
[error] one error found
![Page 105: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/105.jpg)
object Stat {
def mean(xs: Seq[BigDecimal]): BigDecimal =
xs.reduce(_ + _) / xs.size
}
![Page 106: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/106.jpg)
object Order {
def average(orders: Seq[Order]): BigDecimal =
Stat.mean(orders.map(_.evaluate))
}
object Stat {
def mean(xs: Seq[BigDecimal]): BigDecimal =
xs.reduce(_ + _) / xs.size
}
![Page 107: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/107.jpg)
![Page 108: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/108.jpg)
AWESOME!I just need it to work for Doubles and Ints as well! Can you make it
more generic?
![Page 109: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/109.jpg)
object Stat {
def mean(xs: Seq[BigDecimal]): BigDecimal =
xs.reduce(_ + _) / xs.size
}
![Page 110: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/110.jpg)
object Stat {
def mean(xs: Seq[Number]): Number =
xs.reduce(_ + _) / xs.size
}
![Page 111: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/111.jpg)
![Page 112: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/112.jpg)
![Page 113: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/113.jpg)
trait Number[A] {
def value: A
def +(other: Number[A]): Number[A]
def /(other: Number[A]): Number[A]
def /(other: Int): Number[A]
}
![Page 114: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/114.jpg)
trait Number[A] {
def value: A
def +(other: Number[A]): Number[A]
def /(other: Number[A]): Number[A]
def /(other: Int): Number[A]
}
case class BigDecimalNumber(value: BigDecimal) extends Number[BigDecimal] {
def +(other: Number[BigDecimal]) = BigDecimalNumber(value + other.value)
def /(other: Number[BigDecimal]) = BigDecimalNumber(value / other.value)
def /(other: Int) = BigDecimalNumber(value / other)
}
![Page 115: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/115.jpg)
trait Number[A] {
def value: A
def +(other: Number[A]): Number[A]
def /(other: Number[A]): Number[A]
def /(other: Int): Number[A]
}
case class BigDecimalNumber(value: BigDecimal) extends Number[BigDecimal] {
def +(other: Number[BigDecimal]) = BigDecimalNumber(value + other.value)
def /(other: Number[BigDecimal]) = BigDecimalNumber(value / other.value)
def /(other: Int) = BigDecimalNumber(value / other)
}
![Page 116: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/116.jpg)
trait Number[A] {
def value: A
def +(other: Number[A]): Number[A]
def /(other: Number[A]): Number[A]
def /(other: Int): Number[A]
}
case class BigDecimalNumber(value: BigDecimal) extends Number[BigDecimal] {
def +(other: Number[BigDecimal]) = BigDecimalNumber(value + other.value)
def /(other: Number[BigDecimal]) = BigDecimalNumber(value / other.value)
def /(other: Int) = BigDecimalNumber(value / other)
}
case class IntNumber(value: Int) extends Number[Int] {
def +(other: Number[Int]) = IntNumber(value + other.value)
def /(other: Number[Int]) = IntNumber(value / other.value)
def /(other: Int) = IntNumber(value / other)
}
![Page 117: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/117.jpg)
trait Number[A] {
def value: A
def +(other: Number[A]): Number[A]
def /(other: Number[A]): Number[A]
def /(other: Int): Number[A]
}
case class BigDecimalNumber(value: BigDecimal) extends Number[BigDecimal] {
def +(other: Number[BigDecimal]) = BigDecimalNumber(value + other.value)
def /(other: Number[BigDecimal]) = BigDecimalNumber(value / other.value)
def /(other: Int) = BigDecimalNumber(value / other)
}
case class IntNumber(value: Int) extends Number[Int] {
def +(other: Number[Int]) = IntNumber(value + other.value)
def /(other: Number[Int]) = IntNumber(value / other.value)
def /(other: Int) = IntNumber(value / other)
}
case class DoubleNumber(value: Double) extends Number[Double] {
def +(other: Number[Double]) = DoubleNumber(value + other.value)
def /(other: Number[Double]) = DoubleNumber(value / other.value)
def /(other: Int) = DoubleNumber(value / other)
}
![Page 118: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/118.jpg)
object Stat {
def mean(xs: Seq[BigDecimal]): BigDecimal =
xs.reduce(_ + _) / xs.size
}
object Order {
def average(orders: Seq[Order]): BigDecimal =
Stat.mean(orders.map(_.evaluate))
}
![Page 119: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/119.jpg)
object Stat {
def mean[A](xs: Seq[Number[A]]): Number[A] =
xs.reduce(_ + _) / xs.size
}
object Order {
def average(orders: Seq[Order]): BigDecimal =
Stat.mean(orders.map(o => BigDecimalNumber(o.evaluate))).value
}
![Page 120: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/120.jpg)
object Stat {
def mean[A](xs: Seq[Number[A]]): Number[A] =
xs.reduce(_ + _) / xs.size
}
object Order {
def average(orders: Seq[Order]): BigDecimal =
Stat.mean(orders.map(o => BigDecimalNumber(o.evaluate))).value
}
![Page 121: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/121.jpg)
test("should calculate average") {
val o1 = GeneralOrder(DiscountedProduct(product =
BasicProduct(11, BigDecimal("1")), discount = 0.2) :: Nil)
val o2 = GeneralOrder(BasicProduct(10, BigDecimal("4")) :: Nil)
val o3 = GeneralOrder(BasicProduct(10, BigDecimal("10.2")) :: Nil)
Order.average(o1 :: o2 :: o3 :: Nil) should equal(BigDecimal("5.0"))
}
[info] OrderTest:
[info] - should evaluate order
[info] - should calculate average
![Page 122: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/122.jpg)
![Page 123: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/123.jpg)
Domain & Feature RequestsFeature Requests:
● Present current state of orders (JSON)● Calculate final checkout● Calculate average Order price● “Simplify” Orders
![Page 124: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/124.jpg)
Domain & Feature RequestsFeature Requests:
● Present current state of orders (JSON)● Calculate final checkout● Calculate average Order price● “Simplify” Orders
![Page 125: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/125.jpg)
Domain & Feature RequestsFeature Requests:
● Present current state of orders (JSON)● Calculate final checkout● Calculate average Order price● “Simplify” Orders
![Page 126: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/126.jpg)
test("should serialize to json") {
val o1 = GeneralOrder(BasicProduct(10, BigDecimal("10.2")) :: Nil)
val o2 = CancelledOrder
val order = ComplexOrder(o1 :: o2 :: Nil)
val expectedJson = """{
"type: "complex"",
"orders: [{
"type: "general"",
"products: [{"type: "basic"", "id: 10", "price: 10.2"}]"
},
"cancelled order"]"
}"""
JsonSerializer.write(order) should equal(expectedJson)
}
![Page 127: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/127.jpg)
test("should serialize to json") {
val o1 = GeneralOrder(BasicProduct(10, BigDecimal("10.2")) :: Nil)
val o2 = CancelledOrder
val order = ComplexOrder(o1 :: o2 :: Nil)
val expectedJson = """{
"type: "complex"",
"orders: [{
"type: "general"",
"products: [{"type: "basic"", "id: 10", "price: 10.2"}]"
},
"cancelled order"]"
}"""
JsonSerializer.write(order) should equal(expectedJson)
}
[error] OrderTest.scala not found: value JsonSerializer
[error] JsonSerializer.write(order) should equal(expectedJson)
[error] ^
![Page 128: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/128.jpg)
object JsonSerializer {
def write(order: Order): String = ...
}
![Page 129: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/129.jpg)
![Page 130: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/130.jpg)
![Page 131: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/131.jpg)
I have few objects I also need to serialize to JSON. Can you make
your code a bit more generic? Thanks!!!
![Page 132: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/132.jpg)
object JsonSerializer {
def write(order: Order): String = ...
}
![Page 133: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/133.jpg)
object JsonSerializer {
def write(sth: ???): String = ...
}
![Page 134: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/134.jpg)
object JsonSerializer {
def write(serializable: JsonSerializable) = ...
}
![Page 135: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/135.jpg)
object JsonSerializer {
def write(serializable: JsonSerializable) = ...
}
trait JsonSerializable {
def toJson: JsonValue
}
![Page 136: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/136.jpg)
object JsonSerializer {
def write(serializable: JsonSerializable) =
JsonWriter.write(serializable.toJson)
}
trait JsonSerializable {
def toJson: JsonValue
}
![Page 137: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/137.jpg)
object JsonSerializer {
def write(serializable: JsonSerializable) =
JsonWriter.write(serializable.toJson)
}
trait JsonSerializable {
def toJson: JsonValue
}
![Page 138: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/138.jpg)
sealed trait JsonValue
![Page 139: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/139.jpg)
sealed trait JsonValue
case class JsonObject(elem: Map[String, JsonValue]) extends JsonValue
case class JsonArray(elems: List[JsonValue]) extends JsonValue
case class JsonString(value: String) extends JsonValue
case class JsonNumber(value: BigDecimal) extends JsonValue
![Page 140: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/140.jpg)
sealed trait JsonValue
case class JsonObject(elem: Map[String, JsonValue]) extends JsonValue
case class JsonArray(elems: List[JsonValue]) extends JsonValue
case class JsonString(value: String) extends JsonValue
case class JsonNumber(value: BigDecimal) extends JsonValue
object JsonWriter {
def write(json: JsonValue): String =
![Page 141: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/141.jpg)
sealed trait JsonValue
case class JsonObject(elem: Map[String, JsonValue]) extends JsonValue
case class JsonArray(elems: List[JsonValue]) extends JsonValue
case class JsonString(value: String) extends JsonValue
case class JsonNumber(value: BigDecimal) extends JsonValue
object JsonWriter {
def write(json: JsonValue): String = json match {
![Page 142: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/142.jpg)
sealed trait JsonValue
case class JsonObject(elem: Map[String, JsonValue]) extends JsonValue
case class JsonArray(elems: List[JsonValue]) extends JsonValue
case class JsonString(value: String) extends JsonValue
case class JsonNumber(value: BigDecimal) extends JsonValue
object JsonWriter {
def write(json: JsonValue): String = json match {
case JsonNumber(value) => value.toString
}
}
![Page 143: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/143.jpg)
sealed trait JsonValue
case class JsonObject(elem: Map[String, JsonValue]) extends JsonValue
case class JsonArray(elems: List[JsonValue]) extends JsonValue
case class JsonString(value: String) extends JsonValue
case class JsonNumber(value: BigDecimal) extends JsonValue
object JsonWriter {
def write(json: JsonValue): String = json match {
case JsonString(value) => s""""$value""""
case JsonNumber(value) => value.toString
}
}
![Page 144: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/144.jpg)
sealed trait JsonValue
case class JsonObject(elem: Map[String, JsonValue]) extends JsonValue
case class JsonArray(elems: List[JsonValue]) extends JsonValue
case class JsonString(value: String) extends JsonValue
case class JsonNumber(value: BigDecimal) extends JsonValue
object JsonWriter {
def write(json: JsonValue): String = json match {
case JsonArray(elems) => "[" + elems.map(write).mkString(", ") + "]"
case JsonString(value) => s""""$value""""
case JsonNumber(value) => value.toString
}
}
![Page 145: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/145.jpg)
sealed trait JsonValue
case class JsonObject(elem: Map[String, JsonValue]) extends JsonValue
case class JsonArray(elems: List[JsonValue]) extends JsonValue
case class JsonString(value: String) extends JsonValue
case class JsonNumber(value: BigDecimal) extends JsonValue
object JsonWriter {
def write(json: JsonValue): String = json match {
case JsonObject(elems) =>
val entries = for {
(key, value) <- elems
} yield s""""$key: ${write(value)}""""
"{" + entries.mkString(", ") + "}"
case JsonArray(elems) => "[" + elems.map(write).mkString(", ") + "]"
case JsonString(value) => s""""$value""""
case JsonNumber(value) => value.toString
}
}
![Page 146: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/146.jpg)
sealed trait JsonValue
case class JsonObject(elem: Map[String, JsonValue]) extends JsonValue
case class JsonArray(elems: List[JsonValue]) extends JsonValue
case class JsonString(value: String) extends JsonValue
case class JsonNumber(value: BigDecimal) extends JsonValue
object JsonWriter {
def write(json: JsonValue): String = ...
}
![Page 147: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/147.jpg)
sealed trait JsonValue
case class JsonObject(elem: Map[String, JsonValue]) extends JsonValue
case class JsonArray(elems: List[JsonValue]) extends JsonValue
case class JsonString(value: String) extends JsonValue
case class JsonNumber(value: BigDecimal) extends JsonValue
object JsonWriter {
def write(json: JsonValue): String = ...
}
trait JsonSerializable {
def toJson: JsonValue
}
object JsonSerializer {
def write(serializable: JsonSerializable) =
JsonWriter.write(serializable.toJson)
}
![Page 148: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/148.jpg)
sealed trait Order extends Evaluatable[BigDecimal] with JsonSerializable {
def evaluate: BigDecimal
}
![Page 149: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/149.jpg)
sealed trait Order extends Evaluatable[BigDecimal] with JsonSerializable {
def evaluate: BigDecimal
}
case class GeneralOrder(products: List[Product]) extends Order {
def evaluate: BigDecimal = products.foldLeft(BigDecimal("0.0")) {
case (acc, p) => acc + p.evaluate
}
def toJson: JsonValue = JsonObject(Map(
"type" -> JsonString("general"),
"products" -> JsonArray(products.map(_.toJson))
))
}
![Page 150: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/150.jpg)
sealed trait Order extends Evaluatable[BigDecimal] with JsonSerializable {
def evaluate: BigDecimal
}
case object CancelledOrder extends Order {
def evaluate: BigDecimal = BigDecimal("0.0")
def toJson: JsonValue = JsonString("cancelled order")
}
![Page 151: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/151.jpg)
sealed trait Order extends Evaluatable[BigDecimal] with JsonSerializable {
def evaluate: BigDecimal
}
case class ComplexOrder(orders: List[Order]) extends Order {
def evaluate: BigDecimal = orders.foldLeft(BigDecimal("0.0")) {
case (acc, o) => acc + o.evaluate
}
override def toJson: JsonValue = JsonObject(Map(
"type" -> JsonString("complex"),
"orders" -> JsonArray(orders.map(_.toJson)))
)
}
![Page 152: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/152.jpg)
sealed trait Product extends Evaluatable[BigDecimal] with JsonSerializable {
def evaluate: BigDecimal
}
case class BasicProduct(id: Int, price: BigDecimal) extends Product {
def evaluate: BigDecimal = price
def toJson: JsonValue = JsonObject(Map(
"type" -> JsonString("basic"),
"id" -> JsonNumber(BigDecimal(id)),
"price" -> JsonNumber(price)
))
}
![Page 153: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/153.jpg)
sealed trait Product extends Evaluatable[BigDecimal] with JsonSerializable {
def evaluate: BigDecimal
}
case class DiscountedProduct(product: Product, discount: Double) extends Product {
def evaluate: BigDecimal = product.evaluate * (1 - discount)
def toJson: JsonValue = JsonObject(Map(
"type" -> JsonString("discounted"),
"product" -> product.toJson,
"discount" -> JsonNumber(discount)
))
}
![Page 154: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/154.jpg)
sealed trait Product extends Evaluatable[BigDecimal] with JsonSerializable {
def evaluate: BigDecimal
}
case object OutOfStock extends Product {
def evaluate: BigDecimal = BigDecimal("0.0")
def toJson: JsonValue = JsonString("out of stock")
}
![Page 155: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/155.jpg)
test("should serialize to json") {
val o1 = GeneralOrder(BasicProduct(10, BigDecimal("10.2")) :: Nil)
val o2 = CancelledOrder
val order = ComplexOrder(o1 :: o2 :: Nil)
val expectedJson = """{
"type: "complex"",
"orders: [{
"type: "general"",
"products: [{"type: "basic"", "id: 10", "price: 10.2"}]"
},
"cancelled order"]"
}"""
JsonSerializer.write(order) should equal(expectedJson)
}
[info] OrderTest:
[info] - should evaluate order
[info] - should calculate average
[info] - should serialize to json
![Page 156: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/156.jpg)
Domain & Feature RequestsFeature Requests:
● Present current state of orders (JSON)● Calculate final checkout● Calculate average Order price● “Simplify” Orders
![Page 157: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/157.jpg)
Domain & Feature RequestsFeature Requests:
● Present current state of orders (JSON)● Calculate final checkout● Calculate average Order price● “Simplify” Orders
![Page 158: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/158.jpg)
![Page 159: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/159.jpg)
![Page 160: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/160.jpg)
![Page 161: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/161.jpg)
![Page 162: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/162.jpg)
Our goal:
● DRY principle● Separation of concerns● Epic decoupling● Clean API● Minimal Boilerplate
![Page 163: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/163.jpg)
Act.3: “Re-inventing the Wheel”
![Page 164: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/164.jpg)
trait Number[A] {
def value: A
def +(other: Number[A]): Number[A]
def /(other: Number[A]): Number[A]
def /(other: Int): Number[A]
}
case class BigDecimalNumber(value: BigDecimal) extends Number[BigDecimal] {
def +(other: Number[BigDecimal]) = BigDecimalNumber(value + other.value)
def /(other: Number[BigDecimal]) = BigDecimalNumber(value / other.value)
def /(other: Int) = BigDecimalNumber(value / other)
}
case class IntNumber(value: Int) extends Number[Int] {
def +(other: Number[Int]) = IntNumber(value + other.value)
def /(other: Number[Int]) = IntNumber(value / other.value)
def /(other: Int) = IntNumber(value / other)
}
case class DoubleNumber(value: Double) extends Number[Double] {
def +(other: Number[Double]) = DoubleNumber(value + other.value)
def /(other: Number[Double]) = DoubleNumber(value / other.value)
def /(other: Int) = DoubleNumber(value / other)
}
![Page 165: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/165.jpg)
object Stat {
def mean[A](xs: Seq[Number[A]]): Number[A] =
xs.reduce(_ + _) / xs.size
}
object Order {
def average(orders: Seq[Order]): BigDecimal =
Stat.mean(orders.map(o => BigDecimalNumber(o.evaluate))).value
}
![Page 166: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/166.jpg)
object Order {
def average(orders: Seq[Order]): BigDecimal =
Stat.mean(orders.map(o => BigDecimalNumber(o.evaluate))).value
}
![Page 167: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/167.jpg)
object Order {
def average(orders: Seq[Order]): BigDecimal =
Stat.mean(orders.map(_.evaluate))
}
![Page 168: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/168.jpg)
object Stat {
def mean[A](xs: Seq[Number[A]]): Number[A] =
xs.reduce(_ + _) / xs.size
}
object Order {
def average(orders: Seq[Order]): BigDecimal =
Stat.mean(orders.map(_.evaluate))
}
![Page 169: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/169.jpg)
object Stat {
def mean[A](xs: Seq[A]): A =
xs.reduce(_ + _) / xs.size
}
object Order {
def average(orders: Seq[Order]): BigDecimal =
Stat.mean(orders.map(_.evaluate))
}
![Page 170: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/170.jpg)
object Stat {
def mean[A](xs: Seq[A])(implicit number: Number[A]): A =
number.divide(xs.reduce(number.plus),xs.size)
}
object Order {
def average(orders: Seq[Order]): BigDecimal =
Stat.mean(orders.map(_.evaluate))
}
![Page 171: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/171.jpg)
trait Number[A] {
def plus(n1: A, n2: A): A
def divide(n1: A, n2: A): A
def divide(n1: A, n2: Int): A
}
![Page 172: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/172.jpg)
trait Number[A] {
def plus(n1: A, n2: A): A
def divide(n1: A, n2: A): A
def divide(n1: A, n2: Int): A
}
object Number {
implicit object BigDecimalNumber extends Number[BigDecimal] {
def plus(n1: BigDecimal, n2: BigDecimal): BigDecimal = n1 + n2
def divide(n1: BigDecimal, n2: BigDecimal): BigDecimal = n1 / n2
def divide(n1: BigDecimal, n2: Int): BigDecimal = n1 / n2
}
![Page 173: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/173.jpg)
trait Number[A] {
def plus(n1: A, n2: A): A
def divide(n1: A, n2: A): A
def divide(n1: A, n2: Int): A
}
object Number {
implicit object BigDecimalNumber extends Number[BigDecimal] {
def plus(n1: BigDecimal, n2: BigDecimal): BigDecimal = n1 + n2
def divide(n1: BigDecimal, n2: BigDecimal): BigDecimal = n1 / n2
def divide(n1: BigDecimal, n2: Int): BigDecimal = n1 / n2
}
implicit object IntNumber extends Number[Int] {
def plus(n1: Int, n2: Int): Int = n1 + n2
def divide(n1: Int, n2: Int): Int = n1 / n2
}
}
![Page 174: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/174.jpg)
object Stat {
def mean[A](xs: Seq[A])(implicit number: Number[A]): A =
number.divide(xs.reduce(number.plus),xs.size)
}
object Order {
def average(orders: Seq[Order]): BigDecimal =
Stat.mean(orders.map(_.evaluate))
}
![Page 175: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/175.jpg)
object Stat {
def mean[A](xs: Seq[A])(implicit number: Number[A]): A =
number.divide(xs.reduce(number.plus),xs.size)
}
object Order {
def average(orders: Seq[Order]): BigDecimal =
Stat.mean(orders.map(_.evaluate))(BigDecimalNumber)
}
![Page 176: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/176.jpg)
trait Number[A] {
def plus(n1: A, n2: A): A
def divide(n1: A, n2: A): A
def divide(n1: A, n2: Int): A
}
object Number {
implicit object BigDecimalNumber extends Number[BigDecimal] {
def plus(n1: BigDecimal, n2: BigDecimal): BigDecimal = n1 + n2
def divide(n1: BigDecimal, n2: BigDecimal): BigDecimal = n1 / n2
def divide(n1: BigDecimal, n2: Int): BigDecimal = n1 / n2
}
implicit object IntNumber extends Number[Int] {
def plus(n1: Int, n2: Int): Int = n1 + n2
def divide(n1: Int, n2: Int): Int = n1 / n2
}
}
![Page 177: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/177.jpg)
trait Number[A] {
def plus(n1: A, n2: A): A
def divide(n1: A, n2: A): A
def divide(n1: A, n2: Int): A
}
object Number {
implicit object BigDecimalNumber extends Number[BigDecimal] {
def plus(n1: BigDecimal, n2: BigDecimal): BigDecimal = n1 + n2
def divide(n1: BigDecimal, n2: BigDecimal): BigDecimal = n1 / n2
def divide(n1: BigDecimal, n2: Int): BigDecimal = n1 / n2
}
implicit object IntNumber extends Number[Int] {
def plus(n1: Int, n2: Int): Int = n1 + n2
def divide(n1: Int, n2: Int): Int = n1 / n2
}
}
![Page 178: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/178.jpg)
object Stat {
def mean[A](xs: Seq[A])(implicit number: Number[A]): A =
number.divide(xs.reduce(number.plus),xs.size)
}
object Order {
def average(orders: Seq[Order]): BigDecimal =
Stat.mean(orders.map(_.evaluate))(BigDecimalNumber)
}
![Page 179: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/179.jpg)
object Stat {
def mean[A](xs: Seq[A])(implicit number: Number[A]): A =
number.divide(xs.reduce(number.plus),xs.size)
}
object Order {
def average(orders: Seq[Order]): BigDecimal =
Stat.mean(orders.map(_.evaluate))
}
![Page 180: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/180.jpg)
object Stat {
def mean[A](xs: Seq[A])(implicit number: Number[A]): A =
number.divide(xs.reduce(number.plus),xs.size)
}
object Order {
import Number._
def average(orders: Seq[Order]): BigDecimal =
Stat.mean(orders.map(_.evaluate))
}
![Page 181: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/181.jpg)
[info] OrderTest:
[info] - should evaluate order
[info] - should calculate average
[info] - should serialize to json
![Page 182: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/182.jpg)
![Page 183: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/183.jpg)
![Page 184: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/184.jpg)
sealed trait JsonValue
case class JsonObject(elem: Map[String, JsonValue]) extends JsonValue
case class JsonArray(elems: List[JsonValue]) extends JsonValue
case class JsonString(value: String) extends JsonValue
case class JsonNumber(value: BigDecimal) extends JsonValue
object JsonWriter {
def write(json: JsonValue): String = ...
}
trait JsonSerializable {
def toJson: JsonValue
}
object JsonSerializer {
def write(serializable: JsonSerializable) =
JsonWriter.write(serializable.toJson)
}
![Page 185: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/185.jpg)
sealed trait Order extends Evaluatable[BigDecimal] with JsonSerializable
case class GeneralOrder(products: List[Product]) extends Order {
def evaluate: BigDecimal = products.foldLeft(BigDecimal("0.0")) {
case (acc, p) => acc + p.evaluate
}
def toJson: JsonValue = JsonObject(Map(
"type" -> JsonString("general"),
"products" -> JsonArray(products.map(_.toJson))
))
}
![Page 186: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/186.jpg)
test("should serialize to json") {
val o1 = GeneralOrder(BasicProduct(10, BigDecimal("10.2")) :: Nil)
val o2 = CancelledOrder
val order = ComplexOrder(o1 :: o2 :: Nil)
val expectedJson = """{
"type: "complex"",
"orders: [{
"type: "general"",
"products: [{"type: "basic"", "id: 10", "price: 10.2"}]"
},
"cancelled order"]"
}"""
JsonSerializer.write(order) should equal(expectedJson)
}
![Page 187: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/187.jpg)
trait JsonSerializable {
def toJson: JsonValue
}
object JsonSerializer {
def write(serializable: JsonSerializable) =
JsonWriter.write(serializable.toJson)
}
![Page 188: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/188.jpg)
object JsonSerializer {
def write(serializable: JsonSerializable) =
JsonWriter.write(serializable.toJson)
}
![Page 189: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/189.jpg)
trait Json[-A] {
def toJson(a: A): JsonValue
}
object JsonSerializer {
def write(serializable: JsonSerializable) =
JsonWriter.write(serializable.toJson)
}
![Page 190: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/190.jpg)
trait Json[-A] {
def toJson(a: A): JsonValue
}
object JsonSerializer {
def write[A](a: A)(implicit json: Json[A]) =
JsonWriter.write(json.toJson(a))
}
![Page 191: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/191.jpg)
object OrderJson {
implicit object ProductToJson extends Json[Product] {
def toJson(product: Product): JsonValue = ...
}
implicit object OrderToJson extends Json[Order] {
def toJson(order: Order): JsonValue = ...
}
}
![Page 192: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/192.jpg)
implicit object ProductToJson extends Json[Product] {
def toJson(product: Product): JsonValue = product match {
case BasicProduct(id, price) =>
JsonObject(Map(
"type" -> JsonString("basic"),
"id" -> JsonNumber(BigDecimal(id)),
"price" -> JsonNumber(price)
))
case DiscountedProduct(product, discount) =>
JsonObject(Map(
"type" -> JsonString("discounted"),
"product" -> toJson(product),
"discount" -> JsonNumber(discount)
))
case OutOfStock() =>
JsonString("out of stock")
}
}
implicit object OrderToJson extends Json[Order] {
def toJson(order: Order): JsonValue = order match {
case GeneralOrder(products) =>
JsonObject(Map(
"type" -> JsonString("general"),
"products" -> JsonArray(products.map(ProductToJson.toJson))
))
case ComplexOrder(orders) =>
JsonObject(Map(
"type" -> JsonString("complex"),
"orders" -> JsonArray(orders.map(toJson))
))
case CancelledOrder() =>
JsonString("cancelled order")
}
}
![Page 193: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/193.jpg)
implicit object OrderToJson extends Json[Order] {
def toJson(order: Order): JsonValue = order match {
case GeneralOrder(products) =>
JsonObject(Map(
"type" -> JsonString("general"),
"products" -> JsonArray(products.map(ProductToJson.toJson))
))
case ComplexOrder(orders) =>
JsonObject(Map(
"type" -> JsonString("complex"),
"orders" -> JsonArray(orders.map(toJson))
))
case CancelledOrder() =>
JsonString("cancelled order")
}
}
![Page 194: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/194.jpg)
object OrderJson {
implicit object ProductToJson extends Json[Product] {
def toJson(product: Product): JsonValue = ...
}
implicit object OrderToJson extends Json[Order] {
def toJson(order: Order): JsonValue = ...
}
}
![Page 195: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/195.jpg)
test("should serialize to json") {
val o1 = GeneralOrder(BasicProduct(10, BigDecimal("10.2")) :: Nil)
val o2 = CancelledOrder
val order = ComplexOrder(o1 :: o2 :: Nil)
val expectedJson = """{
"type: "complex"",
"orders: [{
"type: "general"",
"products: [{"type: "basic"", "id: 10", "price: 10.2"}]"
},
"cancelled order"]"
}"""
JsonSerializer.write(order) should equal(expectedJson)
}
![Page 196: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/196.jpg)
test("should serialize to json") {
val o1 = GeneralOrder(BasicProduct(10, BigDecimal("10.2")) :: Nil)
val o2 = CancelledOrder
val order = ComplexOrder(o1 :: o2 :: Nil)
val expectedJson = """{
"type: "complex"",
"orders: [{
"type: "general"",
"products: [{"type: "basic"", "id: 10", "price: 10.2"}]"
},
"cancelled order"]"
}"""
JsonSerializer.write(order) should equal(expectedJson)
}
[error] OrderTest.scala could not find implicit value for parameter json: json.Json[jw.
ComplexOrder]
[error] JsonSerializer.write(order) should equal(expectedJson)
![Page 197: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/197.jpg)
test("should serialize to json") {
val o1 = GeneralOrder(BasicProduct(10, BigDecimal("10.2")) :: Nil)
val o2 = CancelledOrder
val order = ComplexOrder(o1 :: o2 :: Nil)
val expectedJson = """{
"type: "complex"",
"orders: [{
"type: "general"",
"products: [{"type: "basic"", "id: 10", "price: 10.2"}]"
},
"cancelled order"]"
}"""
JsonSerializer.write(order) should equal(expectedJson)
}
![Page 198: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/198.jpg)
test("should serialize to json") {
val o1 = GeneralOrder(BasicProduct(10, BigDecimal("10.2")) :: Nil)
val o2 = CancelledOrder
val order = ComplexOrder(o1 :: o2 :: Nil)
val expectedJson = """{
"type: "complex"",
"orders: [{
"type: "general"",
"products: [{"type: "basic"", "id: 10", "price: 10.2"}]"
},
"cancelled order"]"
}"""
import OrderJson._
JsonSerializer.write(order) should equal(expectedJson)
}
![Page 199: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/199.jpg)
test("should serialize to json") {
val o1 = GeneralOrder(BasicProduct(10, BigDecimal("10.2")) :: Nil)
val o2 = CancelledOrder
val order = ComplexOrder(o1 :: o2 :: Nil)
val expectedJson = """{
"type: "complex"",
"orders: [{
"type: "general"",
"products: [{"type: "basic"", "id: 10", "price: 10.2"}]"
},
"cancelled order"]"
}"""
import OrderJson._
JsonSerializer.write(order) should equal(expectedJson)
}
[info] OrderTest:
[info] - should evaluate order
[info] - should calculate average
[info] - should serialize to json
![Page 200: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/200.jpg)
![Page 201: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/201.jpg)
sealed trait Product extends Evaluatable[BigDecimal]
case class BasicProduct(id: Int, price: BigDecimal) extends Product {
def evaluate: BigDecimal = price
}
case class DiscountedProduct(product: Product, discount: Double) extends Product {
def evaluate: BigDecimal = product.evaluate * (1 - discount)
}
case class OutOfStock() extends Product {
def evaluate: BigDecimal = BigDecimal("0.0")
}
![Page 202: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/202.jpg)
sealed trait Order extends Evaluatable[BigDecimal]
case class GeneralOrder(products: List[Product]) extends Order {
def evaluate: BigDecimal = products.foldLeft(BigDecimal("0.0")) {
case (acc, p) => acc + p.evaluate
}
}
case class CancelledOrder() extends Order {
def evaluate: BigDecimal = BigDecimal("0.0")
}
case class ComplexOrder(orders: List[Order]) extends Order {
def evaluate: BigDecimal = orders.foldLeft(BigDecimal("0.0")) {
case (acc, o) => acc + o.evaluate
}
![Page 203: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/203.jpg)
trait Evaluate[-A, T] { def evaluate(a: A): T }
object Order {
implicit object ProductEvaluate extends Evaluate[Product, BigDecimal] {
def evaluate(product: Product): BigDecimal = product match {
case BasicProduct(id, price) => price
case DiscountedProduct(discounted, discount) => evaluate(discounted) * (1 - discount)
case OutOfStock() => BigDecimal("0.0")
}}
implicit object OrderEvaluate extends Evaluate[Order, BigDecimal] {
def evaluate(order: Order): BigDecimal = order match {
case GeneralOrder(products) => products.foldLeft(BigDecimal("0.0")) {
case (acc, p) => acc + ProductEvaluate.evaluate(p)
}
case ComplexOrder(orders) => orders.foldLeft(BigDecimal("0.0")) {
case (acc, o) => acc + evaluate(o)
}
case CancelledOrder() => BigDecimal("0.0")
}}}
![Page 204: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/204.jpg)
trait Evaluate[-A, T] { def evaluate(a: A): T }
object Order {
import Number._
def average(orders: Seq[Order]): BigDecimal =
Stat.mean(orders.map(_.evaluate))
}
![Page 205: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/205.jpg)
trait Evaluate[-A, T] { def evaluate(a: A): T }
object Order {
import Number._
def average(orders: Seq[Order])(implicit ev: Evaluate[Order, BigDecimal]: BigDecimal =
Stat.mean(orders.map(_.evaluate))
}
![Page 206: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/206.jpg)
trait Evaluate[-A, T] { def evaluate(a: A): T }
object Order {
import Number._
def average(orders: Seq[Order])(implicit ev: Evaluate[Order, BigDecimal]: BigDecimal =
Stat.mean(orders.map(o => ev.evaluate(o))
}
![Page 207: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/207.jpg)
![Page 208: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/208.jpg)
sealed trait Order
case class GeneralOrder(products: List[Product]) extends Order
case object CancelledOrder extends Order
case class ComplexOrder(orders: List[Order]) extends Order
sealed trait Product
case class BasicProduct(id: Int, price: BigDecimal) extends Product
case class DiscountedProduct(product: Product,
discount: Double) extends Product
case object OutOfStock extends Product
![Page 209: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/209.jpg)
Act.4: “Renaissance”
![Page 210: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/210.jpg)
Domain & Feature RequestsFeature Requests:
● Present current state of orders (JSON)● Calculate final checkout● Calculate average Order price● “Simplify” Orders
![Page 211: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/211.jpg)
Domain & Feature RequestsFeature Requests:
● Present current state of orders (JSON)● Calculate final checkout● Calculate average Order price● “Simplify” Orders
![Page 212: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/212.jpg)
def simplify(orders: Seq[Order]): Order =
orders.foldLeft(CancelledOrder()) { ?? }
![Page 213: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/213.jpg)
def simplify(orders: Seq[Order]): Order =
orders.foldLeft(CancelledOrder()) {
case (acc, o) => acc + o
}
![Page 214: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/214.jpg)
def simplify(orders: Seq[Order]): Order =
orders.foldLeft(CancelledOrder()) {
case (acc, o) => acc + o
}
trait Addable[A] {
def add(a1: A, a2: A): A
}
![Page 215: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/215.jpg)
def simplify(orders: Seq[Order]): Order =
orders.foldLeft(CancelledOrder()) {
case (acc, o) => acc + o
}
trait Addable[A] {
def add(a1: A, a2: A): A
}
implicit object OrderAddable extends Addable[Order] {
def add(o1: Order, o2: Order): Order = (o1, o2) match {
case (CancelledOrder(), o2) => o2
case (o1, CancelledOrder()) => o1
case (GeneralOrder(ps1), GeneralOrder(ps2)) => GeneralOrder(ps1 ++ ps2)
case (ComplexOrder(os1), ComplexOrder(os2)) => ComplexOrder(os1 ++ os2)
case (o1, ComplexOrder(orders)) => ComplexOrder(o1 :: orders)
case (ComplexOrder(orders), o2) => ComplexOrder(o2 :: orders)
}
}
![Page 216: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/216.jpg)
def simplify(orders: Seq[Order])(implicit addable: Addable[Order]): Order =
orders.foldLeft(CancelledOrder()) {
case (acc, o) => addable.add(acc, o)
}
trait Addable[A] {
def add(a1: A, a2: A): A
}
implicit object OrderAddable extends Addable[Order] {
def add(o1: Order, o2: Order): Order = (o1, o2) match {
case (CancelledOrder(), o2) => o2
case (o1, CancelledOrder()) => o1
case (GeneralOrder(ps1), GeneralOrder(ps2)) => GeneralOrder(ps1 ++ ps2)
case (ComplexOrder(os1), ComplexOrder(os2)) => ComplexOrder(os1 ++ os2)
case (o1, ComplexOrder(orders)) => ComplexOrder(o1 :: orders)
case (ComplexOrder(orders), o2) => ComplexOrder(o2 :: orders)
}
}
![Page 217: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/217.jpg)
def simplify(orders: Seq[Order])(implicit addable: Addable[Order]): Order =
orders.foldLeft(CancelledOrder()) {
case (acc, o) => addable.add(acc, o)
}
![Page 218: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/218.jpg)
def simplify(orders: Seq[Order]): Order = fold(orders)
![Page 219: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/219.jpg)
def simplify(orders: Seq[Order])(implicit addable: Addable[Order]): Order =
orders.foldLeft(CancelledOrder()) {
case (acc, o) => addable.add(acc, o)
}
![Page 220: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/220.jpg)
def simplify(orders: Seq[Order])(implicit addable: Addable[Order]): Order =
orders.foldLeft(CancelledOrder()) {
case (acc, o) => addable.add(acc, o)
}
![Page 221: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/221.jpg)
def simplify(orders: Seq[Order]): Order = fold(orders)
trait AddableWithZero[A] {
def zero: A
def add(a1: A, a2: A): A
}
![Page 222: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/222.jpg)
def simplify(orders: Seq[Order]): Order = fold(orders)
trait AddableWithZero[A] {
def zero: A
def add(a1: A, a2: A): A
}
object AddableWithZero {
def fold[A](values: Seq[A])(implicit addableWithZ: AddableWithZero[A]): A = {
values.fold(addableWithZ.zero){
case (acc, v) => addableWithZ.add(acc, v)
}
}
}
![Page 223: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/223.jpg)
def simplify(orders: Seq[Order]): Order = fold(orders)
trait AddableWithZero[A] {
def zero: A
def add(a1: A, a2: A): A
}
![Page 224: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/224.jpg)
def simplify(orders: Seq[Order]): Order = fold(orders)
trait AddableWithZero[A] {
def zero: A
def add(a1: A, a2: A): A
}
implicit object OrderAddableWithZero extends AddableWithZero[Order] {
def zero = CancelledOrder()
def add(o1: Order, o2: Order): Order = OrderAddable.add(o1,o2)
}
![Page 225: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/225.jpg)
def simplify(orders: Seq[Order]): Order = fold(orders)
trait AddableWithZero[A] {
def zero: A
def add(a1: A, a2: A): A
}
object AddableWithZero {
def fold[A](values: Seq[A])(implicit addableWithZ: AddableWithZero[A]): A = {
values.fold(addableWithZ.zero){
case (acc, v) => addableWithZ.add(acc, v)
}
}
}
![Page 226: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/226.jpg)
![Page 227: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/227.jpg)
trait Evaluate[-A, T] { def evaluate(a: A): T }
object Order {
implicit object ProductEvaluate extends Evaluate[Product, BigDecimal] {
def evaluate(product: Product): BigDecimal = product match {
case BasicProduct(id, price) => price
case DiscountedProduct(discounted, discount) => evaluate(discounted) * (1 - discount)
case OutOfStock() => BigDecimal("0.0")
}}
implicit object OrderEvaluate extends Evaluate[Order, BigDecimal] {
def evaluate(order: Order): BigDecimal = order match {
case GeneralOrder(products) => products.foldLeft(BigDecimal("0.0")) {
case (acc, p) => acc + ProductEvaluate.evaluate(p)
}
case ComplexOrder(orders) => orders.foldLeft(BigDecimal("0.0")) {
case (acc, o) => acc + evaluate(o)
}
case CancelledOrder() => BigDecimal("0.0")
}}}
![Page 228: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/228.jpg)
trait Evaluate[-A, T] { def evaluate(a: A): T }
object Order {
implicit object ProductEvaluate extends Evaluate[Product, BigDecimal] {
def evaluate(product: Product): BigDecimal = product match {
case BasicProduct(id, price) => price
case DiscountedProduct(discounted, discount) => evaluate(discounted) * (1 - discount)
case OutOfStock() => BigDecimal("0.0")
}}
implicit object OrderEvaluate extends Evaluate[Order, BigDecimal] {
def evaluate(order: Order): BigDecimal = order match {
case GeneralOrder(products) => products.foldLeft(BigDecimal("0.0")) {
case (acc, p) => acc + ProductEvaluate.evaluate(p)
}
case ComplexOrder(orders) => orders.foldLeft(BigDecimal("0.0")) {
case (acc, o) => acc + evaluate(o)
}
case CancelledOrder() => BigDecimal("0.0")
}}}
![Page 229: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/229.jpg)
![Page 230: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/230.jpg)
Act.5: “Enlightenment”
![Page 231: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/231.jpg)
Research
![Page 232: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/232.jpg)
Definitions
![Page 233: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/233.jpg)
Definitions● Type classes
![Page 234: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/234.jpg)
Definitions● Type classes
○ Ad-hoc polymorphism
![Page 235: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/235.jpg)
Definitions● Type classes● Abstract Data Type (ADT)
![Page 236: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/236.jpg)
Definitions● Type classes● Abstract Data Type (ADT)● Addable → Semigroup
![Page 237: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/237.jpg)
Definitions● Type classes● Abstract Data Type (ADT)● Addable → Semigroup● AddableWithZero → Monoid
![Page 238: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/238.jpg)
Definitions● Type classes● Abstract Data Type (ADT)● Addable → Semigroup● AddableWithZero → Monoid● Type classes come with laws!
![Page 239: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/239.jpg)
Where to go next1. Functor2. Applicative3. Monad!
All are just type classes with some laws. That’s it!
![Page 240: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/240.jpg)
Before we go, a bit of history...
![Page 241: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/241.jpg)
![Page 242: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/242.jpg)
Links & Resources● https://github.com/rabbitonweb/scala_typeclasses ● https://inoio.de/blog/2014/07/19/type-class-101-semigroup/ ● http://danielwestheide.com/blog/2013/02/06/the-neophytes-guide-to-scala-
part-12-type-classes.html ● https://www.youtube.com/watch?v=sVMES4RZF-8 ● http://homepages.cwi.nl/~storm/teaching/reader/Dijkstra68.pdf● https://www.destroyallsoftware.com/misc/reject.pdf● http://southpark.cc.com/avatar ● http://www.tandemic.com/wp-content/uploads/Definition.png
![Page 243: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/243.jpg)
And that’s all folks!
![Page 244: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/244.jpg)
And that’s all folks!
Paweł Szulc
![Page 245: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/245.jpg)
And that’s all folks!
Paweł Szulc twitter: @rabbitonweb
![Page 246: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/246.jpg)
And that’s all folks!
Paweł Szulc twitter: @rabbitonweb
blog: http://rabbitonweb.com
![Page 247: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/247.jpg)
And that’s all folks!
Paweł Szulc twitter: @rabbitonweb
blog: http://rabbitonweb.com
github: https://github.com/rabbitonweb
![Page 248: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/248.jpg)
And that’s all folks!
Paweł Szulc twitter: @rabbitonweb
blog: http://rabbitonweb.com
github: https://github.com/rabbitonweb
Questions?
![Page 249: Real world gobbledygook](https://reader031.vdocuments.us/reader031/viewer/2022022202/587c5d0a1a28ab633c8b5001/html5/thumbnails/249.jpg)
Thank you!