Scala Native Documentation - Scala Native — Scala Native ...
Introduction to type classes in Scala
-
Upload
yanns -
Category
Technology
-
view
928 -
download
1
Transcript of Introduction to type classes in Scala
![Page 1: Introduction to type classes in Scala](https://reader033.fdocuments.us/reader033/viewer/2022042611/5a6ea9ec7f8b9a7a488b4bf7/html5/thumbnails/1.jpg)
type classes in ScalaAnd how Json Reads/Writes/Formats
work in play framework?
Yann Simon - @simon_yann
![Page 2: Introduction to type classes in Scala](https://reader033.fdocuments.us/reader033/viewer/2022042611/5a6ea9ec7f8b9a7a488b4bf7/html5/thumbnails/2.jpg)
toString, hashCode on modelcase class Person(name: String, age: Int) val persons = List( Person("bob", 34), Person("alice", 34))
persons.toString()res0: String = List(Person(bob,34), Person(alice,34))
persons.hashCode() res1: Int = -408691241
![Page 3: Introduction to type classes in Scala](https://reader033.fdocuments.us/reader033/viewer/2022042611/5a6ea9ec7f8b9a7a488b4bf7/html5/thumbnails/3.jpg)
persons.toStringtoString()List
Person
String Int
toString()
toString() toString()
![Page 4: Introduction to type classes in Scala](https://reader033.fdocuments.us/reader033/viewer/2022042611/5a6ea9ec7f8b9a7a488b4bf7/html5/thumbnails/4.jpg)
persons.hashCodehashCodeList
Person
String Int
hashCode
hashCode hashCode
![Page 5: Introduction to type classes in Scala](https://reader033.fdocuments.us/reader033/viewer/2022042611/5a6ea9ec7f8b9a7a488b4bf7/html5/thumbnails/5.jpg)
What about persons.toJson? persons.toXML? .toCSV? persons.otherHashCode? persons.otherToString?
![Page 6: Introduction to type classes in Scala](https://reader033.fdocuments.us/reader033/viewer/2022042611/5a6ea9ec7f8b9a7a488b4bf7/html5/thumbnails/6.jpg)
Why persons.toString? persons.hashCode?
• part of the standard JVM library package java.lang; public class Object {
public native int hashCode();
public boolean equals(Object obj) { … }
public String toString() { … }
public final native void notify(); public final native void notifyAll();
public final native void wait(long timeout) throws InterruptedException; public final void wait(long timeout, int nanos) throws InterruptedException { … } public final void wait() throws InterruptedException { … } }
![Page 7: Introduction to type classes in Scala](https://reader033.fdocuments.us/reader033/viewer/2022042611/5a6ea9ec7f8b9a7a488b4bf7/html5/thumbnails/7.jpg)
Why persons.toString? persons.hashCode?
• needed by Map, Set, serialization…
• mix technical concerns with domain model
• no liberty for further improvement
• ex: #2011-003 multiple implementations denial-of-service via hash algorithm collisionA variety of programming languages suffer from a denial-of-service (DoS) condition against storage functions of key/value pairs in hash data structures, the condition can be leveraged by exploiting predictable collisions in the underlying hashing algorithms.
![Page 8: Introduction to type classes in Scala](https://reader033.fdocuments.us/reader033/viewer/2022042611/5a6ea9ec7f8b9a7a488b4bf7/html5/thumbnails/8.jpg)
a good toJson?
• Separated from domain model
• Flexible
• User can override library choices
![Page 9: Introduction to type classes in Scala](https://reader033.fdocuments.us/reader033/viewer/2022042611/5a6ea9ec7f8b9a7a488b4bf7/html5/thumbnails/9.jpg)
persons to json
List
Person
String Int
listToJson
personToJson
stringToJson intToJson
trait toJson[A]
![Page 10: Introduction to type classes in Scala](https://reader033.fdocuments.us/reader033/viewer/2022042611/5a6ea9ec7f8b9a7a488b4bf7/html5/thumbnails/10.jpg)
ToJson[A] strategy is a parameter of toJson[A]
def toJson[A](a: A)(serializer: ToJson[A]): String = serializer.serialize(a)
toJson("hello")(stringToJson)toJson(3)(intToJson)toJson(Person("bob", 34))(personToJson)toJson(persons)(listToJson(personToJson))
![Page 11: Introduction to type classes in Scala](https://reader033.fdocuments.us/reader033/viewer/2022042611/5a6ea9ec7f8b9a7a488b4bf7/html5/thumbnails/11.jpg)
find the right ToJson[A] based on type
def toJson[A](a: A)(implicit serializer: ToJson[A]): String = serializer.serialize(a)
toJson("hello") toJson(3) toJson(Person("bob", 34)) toJson(persons)
![Page 12: Introduction to type classes in Scala](https://reader033.fdocuments.us/reader033/viewer/2022042611/5a6ea9ec7f8b9a7a488b4bf7/html5/thumbnails/12.jpg)
find the right ToJson[A] based on type
toJson("hello") // is different from toJson(3)
$ scalac -Xprint:4 Test.scala […] Test.this.toJson[String]("hello")(Test.this.stringToJson); Test.this.toJson[Int](3)(Test.this.intToJson);
![Page 13: Introduction to type classes in Scala](https://reader033.fdocuments.us/reader033/viewer/2022042611/5a6ea9ec7f8b9a7a488b4bf7/html5/thumbnails/13.jpg)
Type classes• Define a contract (ex in ToJson[A]: (a: A) -> String)
• Define strategy for a tree of classes (like the domain model)
• Use type for find the suitable implementation
• Each implicit can be overridden / set explicitly => the user has the power to override defaults
• Type classes resolved at compilation time
• Be sure that the strategy is defined for each class
• No runtime introspection necessary
![Page 14: Introduction to type classes in Scala](https://reader033.fdocuments.us/reader033/viewer/2022042611/5a6ea9ec7f8b9a7a488b4bf7/html5/thumbnails/14.jpg)
In Play! frameworkpackage play.api.libs.json
object Json {
def toJson[T](o: T)(implicit tjs: Writes[T]): JsValue = tjs.writes(o) def fromJson[T](json: JsValue)(implicit fjs: Reads[T]): JsResult[T] = fjs.reads(json) }
/** * Default Serializers. */trait DefaultWrites { implicit object IntWrites extends Writes[Int] { def writes(o: Int) = JsNumber(o) }
implicit object StringWrites extends Writes[String] { def writes(o: String) = JsString(o) }
implicit def traversableWrites[A: Writes] = new Writes[Traversable[A]] { def writes(as: Traversable[A]) = JsArray(as.map(toJson(_)).toSeq) }}
![Page 15: Introduction to type classes in Scala](https://reader033.fdocuments.us/reader033/viewer/2022042611/5a6ea9ec7f8b9a7a488b4bf7/html5/thumbnails/15.jpg)
In Play! frameworkpackage play.api.libs.json
trait Format[A] extends Writes[A] with Reads[A]
/** * Default Json formatters. */trait DefaultFormat { implicit def GenericFormat[T](implicit fjs: Reads[T], tjs: Writes[T]): Format[T] = { new Format[T] { def reads(json: JsValue) = fjs.reads(json) def writes(o: T) = tjs.writes(o) } }}
![Page 16: Introduction to type classes in Scala](https://reader033.fdocuments.us/reader033/viewer/2022042611/5a6ea9ec7f8b9a7a488b4bf7/html5/thumbnails/16.jpg)
implicitly syntaxdef toJson[A](a: A)(implicit toJson: ToJson[A]): String = toJson.serialize(a)
// can be written as:def toJson[A : ToJson](a: A): String = implicitly[ToJson[A]].serialize(a)
toJson("hello") toJson(3) toJson(Person("bob", 34)) toJson(persons)
![Page 17: Introduction to type classes in Scala](https://reader033.fdocuments.us/reader033/viewer/2022042611/5a6ea9ec7f8b9a7a488b4bf7/html5/thumbnails/17.jpg)
persons.toJsonimplicit class JsonOps[A](a: A)(implicit ser: ToJson[A]) { def toJson: String = ser.serialize(a)} "hello".toJson3.toJsonPerson("bob", 34).toJsonpersons.toJson
![Page 18: Introduction to type classes in Scala](https://reader033.fdocuments.us/reader033/viewer/2022042611/5a6ea9ec7f8b9a7a488b4bf7/html5/thumbnails/18.jpg)
Questions?
• code on https://github.com/yanns/scala-type-classes-demo
• more info:
• https://non.github.io/cats/typeclasses.html
• http://danielwestheide.com/blog/2013/02/06/the-neophytes-guide-to-scala-part-12-type-classes.html