SlideShare a Scribd company logo
SO VARIOUS
POLYMORPHISM
IN SCALA
Boris Trofimov
@ Sigma Software
@b0ris_1
AGENDA
WHY
SCALA
CONTEXT
MAP
POLYMORPHISM
DEFINITION
BASIC
DEGREE
BACHELOR
DEGREE
MAST
DEGR
Why Scala?
Context Map
Polymorphism Definition
Basic Degree
Bachelor degree
Master degree
Ph.D
DO YOU ACCEPT
SAPIR–WHORF
HYPOTHESIS?
WHY
SCALA
CONTEXT
MAP
POLYMORPHISM
DEFINITION
BASIC
DEGREE
BACHELOR
DEGREE
MAST
DEGR
WHY
SCALA
AGENDA
WHY
SCALA
CONTEXT
MAP
POLYMORPHISM
DEFINITION
BASIC
DEGREE
BACHELOR
DEGREE
MAST
DEGR
AGENDA
 Object-Oriented Meets Functional
 Strongly Functional
 It makes you love your code again
 Scalable grammar
 Hello Domain Specific Languages (DSL)
 Inexhaustible language for every day
SCALA JAVA
class A (p: String) class A {
final String p;
public A(String p) {
this.p = p;
}
}
val variable = "string" final String variable = "string" ;
def func (p: String): String = {...} String func (String p) { ... }
trait A { def run() } interface A {
void run() ;
}
сlass A[B <: C] { … } class A <B extends C> { ... }
object A { … } Class - Singleton definition
CONTEXT
MAP
POLYMORPHISM
DEFINITION
BASIC
DEGREE
BACHELOR
DEGREE
MAST
DEGR
CONTEXT
MAP
WHY
SCALA
AGENDA
CONTEXT
MAP
POLYMORPHISM
DEFINITION
BASIC
DEGREE
BACHELOR
DEGREE
MAST
DEGR
POLYMORPHISM
DEFINITION
WHY
SCALA
AGENDA
 Ability of language to handle data of different types in the same way.
 Provision of a single interface to entities of different types.
 Particular code is able to handle data of different types.
 Way to change code behavior via input parameters without direct
modification (respecting Open-Closed Principle)
Polymorphic code will be
highlighted in a frame
BASIC
DEGREE
AD-HOC SUBTYPING
PARAMETRIC
POLYMORPHISM
REFLECTION
SUBTYPING
FUNCTIONAL
SUBTYPING
abstract class A{
def method() {
...
this.doSomething
...
}
// abstract method
def doSomething
}
class B extends A{
override def doSomething { … }
}
class B extends C{
override def doSomething { … }
}
AD-HOC SUBTYPING
PARAMETRIC
POLYMORPHISM
REFLECTION
SUBTYPING
FUNCTIONAL
SUBTYPING
trait A
class B extends A
class C extends A
class List {
def add(a : A) = {
...
}
}
SUBTYPINGAD-HOC
AD-HOC SUBTYPING
PARAMETRIC
POLYMORPHISM
REFLECTION
SUBTYPING
FUNCTIONAL
SUBTYPING
AD-HOC
class MyClass {
def addItem[A](a: A): List[A] = {
val list = new ListBuffer[A]
list += a
list.toList()
}
// B should be inheritor of ParentClass
def addItem[B <: ParentClass] (b: B) : List[A] = {
val list = new ListBuffer[B]
list += b
list.toList()
}
}
PARAMETRIC
POLYMORPHISM
AD-HOC SUBTYPING
PARAMETRIC
POLYMORPHISM
REFLECTION
SUBTYPING
FUNCTIONAL
SUBTYPING
AD-HOC
REFLECTION
SUBTYPING
class MyClass {
def doSomething(a: Object) = {
...
val method = a.getClass().getMethod("run", Int)
method.invoke(a, 1)
...
}
}
AD-HOC SUBTYPING
PARAMETRIC
POLYMORPHISM
REFLECTION
SUBTYPING
FUNCTIONAL
SUBTYPING
AD-HOC
FUNCTIONAL
SUBTYPING
class List[A] {
...
def sort(data : (A, A) => Int ) : List[A] = {
...
}
}
object Application extends App{
val list = List(7,8,5,4)
list.sort( (a,b) => a – b ) // _-_
}
BACHELOR
DEGREE
DUCK
SUBTYPING
CAKE
PATTERN
CHAINING
POLYMORPHISM
When I see a bird that walks like a duck and swims like a duck and quacks
like a duck, I call that bird a duck
class MyClass {
def doSomething(a : type { def run(i : Int) } ) = {
...
a.run(1)
...
}
}
class DuckClass {
def run(i : Int) {
...
}
}
new MyClass().doSomething( new DuckClass() )
Caution: Reflection!
CAKE
PATTERN
CHAINING
POLYMORPHISM
DUCK
SUBTIPING
CAKE
PATTERN
trait ComponentA {
def doThis() : String
}
trait ComponentB {
def doThat() : String
}
class OurComponent extends ComponentA with ComponentB {
def doSomething() = doThis() + doThat()
}
CAKE
PATTERN
CHAINING
POLYMORPHISM
DUCK
SUBTIPING
CAKE
PATTERN
trait ComponentA {
def doThis() : String
}
trait ComponentB {
def doThat() : String
}
class OurComponent extends ComponentA with ComponentB {
def doSomething() = doThis() + doThat()
}
trait ComponentAImpl extends ComponentA {
def doThis() = "hello Component A"
}
trait ComponentBImpl extends ComponentB {
def doThat() = "hello Component B"
}
CAKE
PATTERN
CHAINING
POLYMORPHISM
DUCK
SUBTIPING
CAKE
PATTERN
trait ComponentA {
def doThis() : String
}
trait ComponentB {
def doThat() : String
}
class OurComponent extends ComponentA with ComponentB {
def doSomething() = doThis() + doThat()
}
trait ComponentAImpl extends ComponentA {
def doThis() = "hello Component A"
}
trait ComponentBImpl extends ComponentB {
def doThat() = "hello Component B"
}
object Main extends App{
val obj = new OurComponent with ComponentAImpl with ComponentBImpl
println( obj.doSomething() )
}
CAKE
PATTERN
CHAINING
POLYMORPHISM
DUCK
SUBTIPING
CHAINING
POLYMORPHISM
trait AbstractOperation { def run() }
class SaveToDataBaseOperation extends AbstractOperation {
override def run(): Unit = {
println("Save it to database")
}
}
CAKE
PATTERN
CHAINING
POLYMORPHISM
DUCK
SUBTIPING
CHAINING
POLYMORPHISM
trait AbstractOperation { def run() }
class SaveToDataBaseOperation extends AbstractOperation {
override def run(): Unit = {
println("Save it to database")
}
}
// decorating with audit
trait AuditDecorator extends AbstractOperation {
abstract override def run(): Unit = {
println("Entering AuditDecorator")
super.run()
println("Leaving AuditDecorator")
}
}
// decorating with caching
trait CachingDecorator extends AbstractOperation {
abstract override def run(): Unit = {
println("Caching something")
super.run()
}
}
CAKE
PATTERN
CHAINING
POLYMORPHISM
DUCK
SUBTIPING
CHAINING
POLYMORPHISM
trait AbstractOperation { def run() }
class SaveToDataBaseOperation extends AbstractOperation {
override def run(): Unit = {
println("Save it to database")
}
}
// decorating with audit
trait AuditDecorator extends AbstractOperation {
abstract override def run(): Unit = {
println("Entering AuditDecorator")
super.run()
println("Leaving AuditDecorator")
}
}
// decorating with caching
trait CachingDecorator extends AbstractOperation {
abstract override def run(): Unit = {
println("Caching something")
super.run()
}
}
object MyApp extends App {
val operation =
new SaveToDataBaseOperation with CachingDecorator with AuditDecorator
operation.run()
}
OUTPUT:
>Entering AuditDecorator
>Caching something
>Save it to database
>Leaving AuditDecorator
MASTER
DEGREE
TYPE CLASSES
RETROACTIVE
POLYMORPHISM
IMPLICIT DI
TYPE
CONSTRUCTORS
object Test{
println( Arithmetics.add("Hello", " World") ) // returns “Hello World”
println( Arithmetics.add(2,3) ) // returns 5
// Compile Error, could not find corresponding implicit object
println( Arithmetics.add(123.0, -45.345) )
}
F-BOUNDED
POLYMORPHISM
TYPE CLASSES
RETROACTIVE
POLYMORPHISM
IMPLICIT DI
TYPE
CONSTRUCTORS
object Test{
println( Arithmetics.add("Hello", " World") ) // returns “Hello World”
println( Arithmetics.add(2,3) ) // returns 5
// Compile Error, could not find corresponding implicit object
println( Arithmetics.add(123.0, -45.345) )
}
trait NumericLike[T] {
def plus(x : T, y: T) : T
}
implicit object TInteger extends NumericLike[Int]{
def plus(x : Int, y: Int) : Int = x + y
}
implicit object TString extends NumericLike[String]{
def plus(x : String, y: String) : String = x + y
}
object Arithmetics{
// generalized `add` method
def add[T : NumericLike](x:T, y:T): T = {
val engine = implicitly[NumericLike[T]]
engine.plus(x, y)
}
}
Type Class Pattern
F-BOUNDED
POLYMORPHISM
Type Class can be
treated as an advocate
for specific type T
TYPE CLASSES
RETROACTIVE
POLYMORPHISM
IMPLICIT DI
TYPE
CONSTRUCTORS
F-BOUNDED
POLYMORPHISM
RETROACTIVE
POLYMORPHISM
TYPE CLASSES
https://github.com/spray/spray-json
import spray.json._
import DefaultJsonProtocol._
// from json
val source = """{ "some": ["JSON source"] }"""
val ast = source.parseJson
val myObject = ast.convertTo[Map[String, Array[String]]]
// to json
val jsonAst = Map(Array("1"), Array("1")).toJson // to ast
val json = jsonAst.prettyPrint // or .compactPrint
class Color(val name: String, val red: Int, val green: Int, val blue: Int)
// custom serializer via type class
object MyJsonProtocol extends DefaultJsonProtocol {
implicit object ColorJsonFormat extends RootJsonFormat[Color] {
def write(c: Color) = . . .
def read(value: JsValue) = ...
}
}
import MyJsonProtocol._
val json = Color("CadetBlue", 95, 158, 160).toJson
val color = json.convertTo[Color]
The ability to extend functionality of a library without modifying its source is known
as Retroactive Extension
TYPE CLASSES
RETROACTIVE
POLYMORPHISM
IMPLICIT DI
TYPE
CONSTRUCTORS
F-BOUNDED
POLYMORPHISM
IMPLICIT DI
RETROACTIVE
POLYMORPHISM
trait Future[+T] extends Awaitable[T] {
…
def filter(pred: T => Boolean) (implicit executor: ExecutionContext):
Future[T] =
map {
r => if (pred(r)) r else throw new
NoSuchElementException("Future.filter predicate is not satisfied")
}
def map[S](f: T => S) (implicit executor: ExecutionContext): Future[S] = {
// transform(f, identity)
val p = Promise[S]()
onComplete { v => p complete (v map f) }
p.future
}
}
TYPE CLASSES
Dependency Injection per
method
TYPE CLASSES
RETROACTIVE
POLYMORPHISM
IMPLICIT DI
TYPE
CONSTRUCTORS
F-BOUNDED
POLYMORPHISM
IMPLICIT DI
RETROACTIVE
POLYMORPHISM
trait Future[+T] extends Awaitable[T] {
…
def filter(pred: T => Boolean) (implicit executor: ExecutionContext):
Future[T] =
map {
r => if (pred(r)) r else throw new
NoSuchElementException("Future.filter predicate is not satisfied")
}
def map[S](f: T => S) (implicit executor: ExecutionContext): Future[S] = {
// transform(f, identity)
val p = Promise[S]()
onComplete { v => p complete (v map f) }
p.future
}
}
...
import scala.concurrent.ExecutionContext.Implicits.global
val future = Future { 12345 }. map { x => x + 1} // _ + 1
TYPE CLASSES
Dependency Injection per
method
TYPE CLASSES
RETROACTIVE
POLYMORPHISM
IMPLICIT DI
TYPE
CONSTRUCTORS
F-BOUNDED
POLYMORPHISM
IMPLICIT DI
RETROACTIVE
POLYMORPHISM
trait Future[+T] extends Awaitable[T] {
…
def filter(pred: T => Boolean) (implicit executor: ExecutionContext):
Future[T] =
map {
r => if (pred(r)) r else throw new
NoSuchElementException("Future.filter predicate is not satisfied")
}
def map[S](f: T => S) (implicit executor: ExecutionContext): Future[S] = {
// transform(f, identity)
val p = Promise[S]()
onComplete { v => p complete (v map f) }
p.future
}
}
...
import scala.concurrent.ExecutionContext.Implicits.global
val future = Future { 12345 }. map { x => x + 1} // _ + 1
// test code
implicit val executionContext = mock[ExecutionContext]
val future = Future { 12345 }. map { _ + 1}
TYPE CLASSES
Dependency Injection per
method
TYPE CLASSES
RETROACTIVE
POLYMORPHISM
IMPLICIT DI
TYPE
CONSTRUCTORS
F-BOUNDED
POLYMORPHISM
TYPE
CONSTRUCTORS
TYPE CLASSES
More about motivation and examples
http://adriaanm.github.io/files/higher.pdf
Way to build generalized
types to take generics as
a parameter
TYPE CLASSES
RETROACTIVE
POLYMORPHISM
IMPLICIT DI
TYPE
CONSTRUCTORS
F-BOUNDED
POLYMORPHISM
TYPE
CONSTRUCTORS
TYPE CLASSES
object Test{
Operations.tupleize(Some(1), Some(2)) // returns Some( (1,2) )
Operations.tupleize(List(1,3), List (2,4)) //returns List( (1,2) , (3,4) )
}
TYPE CLASSES
RETROACTIVE
POLYMORPHISM
IMPLICIT DI
TYPE
CONSTRUCTORS
F-BOUNDED
POLYMORPHISM
TYPE
CONSTRUCTORS
TYPE CLASSES
object Test{
Operations.tupleize(Some(1), Some(2)) // returns Some( (1,2) )
Operations.tupleize(List(1,3), List (2,4)) //returns List( (1,2) , (3,4) )
}
trait ContainerHandler[M[_]] {
def put[A](x: A): M[A]
def get[A](m: M[A]): A
}
object Operations{
def tupleize[M[_]: ContainerHandler, A, B](fst: M[A], snd: M[B]) = {
val engine = implicitly[ContainerHandler[M]]
engine.put( Pair(engine.get(fst), engine.get(snd)) )
}
}
TYPE CLASSES
RETROACTIVE
POLYMORPHISM
IMPLICIT DI
TYPE
CONSTRUCTORS
F-BOUNDED
POLYMORPHISM
TYPE
CONSTRUCTORS
TYPE CLASSES
object Test{
Operations.tupleize(Some(1), Some(2)) // returns Some( (1,2) )
Operations.tupleize(List(1,3), List (2,4)) //returns List( (1,2) , (3,4) )
}
trait ContainerHandler[M[_]] {
def put[A](x: A): M[A]
def get[A](m: M[A]): A
}
object Operations{
def tupleize[M[_]: ContainerHandler, A, B](fst: M[A], snd: M[B]) = {
val engine = implicitly[ContainerHandler[M]]
engine.put( Pair(engine.get(fst), engine.get(snd)) )
}
}
implicit val listHandler =
new ContainerHandler[List]{ def put[A](x: A) = List(x); def get[A](m: List[A]) = m.head
}
implicit val optionHandler =
new ContainerHandler[Some]{ def put[A](x: A) = Some(x); def get[A](m: Some[A]) = m.get
}
trait Account[T <: Account[T] ] {
def addFunds(amount: BigDecimal): T
}
class CheckingAccount(total: BigDecimal, trxMaxCount: Int)
extends Account[CheckingAccount] {
def addFunds(amount: BigDecimal) : CheckingAccount =
new CheckingAccount(total + amount, trxMaxCount)
}
class SavingAccount(total: BigDecimal) extends Account[SavingAccount] {
def addFunds(amount: BigDecimal) : SavingAccount =
new SavingAccount(total + amount)
}
TYPE CLASSES
RETROACTIVE
POLYMORPHISM
IMPLICIT DI
TYPE
CONSTRUCTORS
F-BOUNDED
POLYMORPHISM
F-BOUNDED
POLYMORPHISM
TYPE CLASSES
How to define function that, though defined in terms of a supertype, will when
passed a value of some subtype will always return a value of the same subtype as
its argument?
trait Account {
def addFunds(amount: BigDecimal): Account //???
}
trait Account[T <: Account[T] ] {
def addFunds(amount: BigDecimal): T
}
class CheckingAccount(total: BigDecimal, trxMaxCount: Int)
extends Account[CheckingAccount] {
def addFunds(amount: BigDecimal) : CheckingAccount =
new CheckingAccount(total + amount, trxMaxCount)
}
class SavingAccount(total: BigDecimal) extends Account[SavingAccount] {
def addFunds(amount: BigDecimal) : SavingAccount =
new SavingAccount(total + amount)
}
TYPE CLASSES
RETROACTIVE
POLYMORPHISM
IMPLICIT DI
TYPE
CONSTRUCTORS
F-BOUNDED
POLYMORPHISM
F-BOUNDED
POLYMORPHISM
TYPE CLASSES
How to define function that, though defined in terms of a supertype, will when
passed a value of some subtype will always return a value of the same subtype as
its argument?
trait Account {
def addFunds(amount: BigDecimal): Account //???
}
TYPE CLASSES
RETROACTIVE
POLYMORPHISM
IMPLICIT DI
TYPE
CONSTRUCTORS
F-BOUNDED
POLYMORPHISM
F-BOUNDED
POLYMORPHISM
TYPE CLASSES
object Account {
val feePercentage = BigDecimal("0.02")
val feeThreshold = BigDecimal("10000.00")
def deposit[T <: Account[T]](amount: BigDecimal, account: T): T = {
if (amount < feeThreshold) account.addFunds(amount - (amount * feePercentage))
else account.addFunds(amount)
}
http://logji.blogspot.com/2012/11/f-bounded-type-polymorphism-give-up-now.html
TYPE CLASSES
RETROACTIVE
POLYMORPHISM
IMPLICIT DI
TYPE
CONSTRUCTORS
F-BOUNDED
POLYMORPHISM
F-BOUNDED
POLYMORPHISM
TYPE CLASSES
object Account {
val feePercentage = BigDecimal("0.02")
val feeThreshold = BigDecimal("10000.00")
def deposit[T <: Account[T]](amount: BigDecimal, account: T): T = {
if (amount < feeThreshold) account.addFunds(amount - (amount * feePercentage))
else account.addFunds(amount)
}
def debitAll(amount: BigDecimal, accounts: List[T forSome { type T <: Account[T] }]):
List[T forSome { type T <: Account[T] }] = {
accounts map { _.addFunds(-amount) }
}
}
object Test {
val list = List[T forSome { type T <: Account[T] }](
new CheckingAccount(BigDecimal("0"), 10),
new SavingAccount(BigDecimal("0")))
Account.debitAll(BigDecimal("10.00"), list)
}
The second frame uses
trick with existential
types to store in one
collection
http://logji.blogspot.com/2012/11/f-bounded-type-polymorphism-give-up-now.html
Scala Puzzle
def gen2(i: Int): Stream[Int] = Stream(i) append gen2(i+1)
println(gen2(0).take(10).to[List])
// > List(0, 1, 2, 3, 4, 5, 6, 7, 8, 9)
def gen(i: Int): Stream[Int] = Stream(i) ++ gen(i+1)
println(gen(0).take(10).to[List])
// > List(0, 1, 2, 3, 4, 5, 6, 7, 8, 9)
(2) The first fails, the second
succeeds
(1) Both will fail with
StackOverflowError
(4) The second fails, the first
succeeds
(3) Both will succeed
1
2
Ph.D
DEGREE
TYPE CLASSES
POLYMORPHIC
FUNCTIONS
RETROACTIVE
POLYMORPHISM
We treat type aliases like
abstract virtual functions
passing and returning types, for
instance:
def Prev : Nat
def Plus(A: Nat) : Nat
VIRTUAL TYPES
object Factorial extends App {
trait Nat {
type Prev <: Nat
type Plus[A <: Nat] <: Nat
type Times[A <: Nat] <: Nat
type Factorial <: Nat
}
trait _0 extends Nat {
type Prev = _0
type Plus[A <: Nat] = A
type Times[A <: Nat] = _0
type Factorial = _1
}
trait Succ[N <: Nat] extends Nat {
type This = Succ[N]
type Prev = N
type Times[A <: Nat] = A#Plus[N#Times[A]]
type Plus[A <: Nat] = N#Plus[Succ[A]]
type Factorial = This#Times[Prev#Factorial]
}
type _1 = Succ[_0]
type _2 = Succ[_1]
type _3 = Succ[_2]
type _4 = Succ[_3]
type _5 = Succ[_4]
type _6 = Succ[_5]
type _7 = Succ[_6]
type _8 = Succ[_7]
type _9 = Succ[_8]
// Calculate 3! = 6
implicitly[_3#Factorial =:= _6]
}
https://gist.github.com/mkleen/9290750
TYPE CLASSES
POLYMORPHIC
FUNCTIONS
VIRTUAL TYPES
POLYMORPHIC
FUNCTIONS
https://github.com/milessabin/shapeless/wiki/Feature-overview:-shapeless-2.0.0
 Scala function values are monomorphic due to interface Function1[U,V] { .. }
 Shapeless library allows to avoid this limitation
 Polymorphic functions allow to process heterogeneous collections (HLists)
import poly._
// choose is a function from Sets to Options with no type specific cases
object choose extends (Set ~> Option) {
def apply[T](s : Set[T]) = s.headOption
}
scala> choose(Set(1, 2, 3))
res0: Option[Int] = Some(1)
scala> choose(Set('a', 'b', 'c'))
res1: Option[Char] = Some(a)
scala> val sets = Set(1) :: Set("foo") :: HNil
scala> val opts = sets map choose // map selects cases of choose for each HList element
opts: Option[Int] :: Option[String] :: HNil = Some(1) :: Some(foo) :: HNil
Define polymorphic function
TYPE CLASSES
POLYMORPHIC
FUNCTIONS
VIRTUAL TYPES
POLYMORPHIC
FUNCTIONS
https://github.com/milessabin/shapeless/wiki/Feature-overview:-shapeless-2.0.0
 Scala function values are monomorphic due to interface Function1[U,V] { .. }
 Shapeless library allows to avoid this limitation
 Polymorphic functions allow to process heterogeneous collections (HLists)
import poly._
// choose is a function from Sets to Options with no type specific cases
object choose extends (Set ~> Option) {
def apply[T](s : Set[T]) = s.headOption
}
scala> choose(Set(1, 2, 3))
res0: Option[Int] = Some(1)
scala> choose(Set('a', 'b', 'c'))
res1: Option[Char] = Some(a)
scala> val sets = Set(1) :: Set("foo") :: HNil
scala> val opts = sets map choose // map selects cases of choose for each HList element
opts: Option[Int] :: Option[String] :: HNil = Some(1) :: Some(foo) :: HNil
It behaves like an usual function
Define polymorphic function
TYPE CLASSES
POLYMORPHIC
FUNCTIONS
VIRTUAL TYPES
POLYMORPHIC
FUNCTIONS
https://github.com/milessabin/shapeless/wiki/Feature-overview:-shapeless-2.0.0
 Scala function values are monomorphic due to interface Function1[U,V] { .. }
 Shapeless library allows to avoid this limitation
 Polymorphic functions allow to process heterogeneous collections (HLists)
import poly._
// choose is a function from Sets to Options with no type specific cases
object choose extends (Set ~> Option) {
def apply[T](s : Set[T]) = s.headOption
}
scala> choose(Set(1, 2, 3))
res0: Option[Int] = Some(1)
scala> choose(Set('a', 'b', 'c'))
res1: Option[Char] = Some(a)
scala> val sets = Set(1) :: Set("foo") :: HNil
scala> val opts = sets map choose // map selects cases of choose for each HList element
opts: Option[Int] :: Option[String] :: HNil = Some(1) :: Some(foo) :: HNil
HList runs polymorphic function
It behaves like an usual function
Define polymorphic function
REFERENCES
 http://adriaanm.github.io/files/higher.pdf
 http://twitter.github.io/scala_school/advanced-types.html
 http://logji.blogspot.com/2012/11/f-bounded-type-polymorphism-give-up-
now.html
 http://danielwestheide.com/blog/2013/02/06/the-neophytes-guide-to-scala-
part-12-type-classes.html
 https://gist.github.com/mkleen/9290750
 http://apocalisp.wordpress.com/2010/06/08/type-level-programming-in-
scala/
THANK YOU

More Related Content

PDF
Making Java REST with JAX-RS 2.0
PDF
RESTful Web Services with Jersey
PDF
Novelties in Java EE 7: JAX-RS 2.0 + IPT REST HATEOAS Polling Demo @ BGOUG Co...
ODP
RestFull Webservices with JAX-RS
ODP
RESTful Web Services with JAX-RS
PPTX
Restful web services with java
PPT
Developing RESTful WebServices using Jersey
PPT
Introduction to JAX-RS
Making Java REST with JAX-RS 2.0
RESTful Web Services with Jersey
Novelties in Java EE 7: JAX-RS 2.0 + IPT REST HATEOAS Polling Demo @ BGOUG Co...
RestFull Webservices with JAX-RS
RESTful Web Services with JAX-RS
Restful web services with java
Developing RESTful WebServices using Jersey
Introduction to JAX-RS

What's hot (20)

PDF
Jersey and JAX-RS
PPT
Using Java to implement RESTful Web Services: JAX-RS
ODP
RESTing with JAX-RS
PPTX
RESTEasy
PPT
RESTful services with JAXB and JPA
PPTX
RESTful Web Services
PDF
JAX-RS 2.0: New and Noteworthy in RESTful Web services API at JAX London
PDF
Json to hive_schema_generator
PPT
RESTful SOA - 中科院暑期讲座
PPT
JSP Standart Tag Lİbrary - JSTL
PPTX
jstl ( jsp standard tag library )
PPT
Jstl Guide
PPTX
Introduction to RESTful Webservices in JAVA
PPT
Java serverpages
PDF
03 form-data
PPT
Oracle database - Get external data via HTTP, FTP and Web Services
PDF
Javaone 2010
PPT
Easy rest service using PHP reflection api
PDF
Deepak khetawat sling_models_sightly_jsp
PDF
Consuming RESTful services in PHP
Jersey and JAX-RS
Using Java to implement RESTful Web Services: JAX-RS
RESTing with JAX-RS
RESTEasy
RESTful services with JAXB and JPA
RESTful Web Services
JAX-RS 2.0: New and Noteworthy in RESTful Web services API at JAX London
Json to hive_schema_generator
RESTful SOA - 中科院暑期讲座
JSP Standart Tag Lİbrary - JSTL
jstl ( jsp standard tag library )
Jstl Guide
Introduction to RESTful Webservices in JAVA
Java serverpages
03 form-data
Oracle database - Get external data via HTTP, FTP and Web Services
Javaone 2010
Easy rest service using PHP reflection api
Deepak khetawat sling_models_sightly_jsp
Consuming RESTful services in PHP
Ad

Viewers also liked (20)

PDF
Scalding big ADta
PDF
Audience counting at Scale
PDF
Play with play!
PPTX
RxJava Applied
PDF
Bending Spark towards enterprise needs
PPTX
Scalding Big (Ad)ta
ODP
MongoDB Distilled
PDF
Faster persistent data structures through hashing
PPTX
Effective Programming In Scala
ODP
Type Parameterization
PDF
Continuous DB migration based on carbon5 framework
PDF
Scala collections
PPTX
Spring AOP Introduction
KEY
Simple Scala DSLs
PPTX
Scala’s implicits
PDF
Real-World Scala Design Patterns
PDF
Scala Implicits - Not to be feared
PPTX
Clustering Java applications with Terracotta and Hazelcast
PDF
Variance in scala
PPTX
Types by Adform Research, Saulius Valatka
Scalding big ADta
Audience counting at Scale
Play with play!
RxJava Applied
Bending Spark towards enterprise needs
Scalding Big (Ad)ta
MongoDB Distilled
Faster persistent data structures through hashing
Effective Programming In Scala
Type Parameterization
Continuous DB migration based on carbon5 framework
Scala collections
Spring AOP Introduction
Simple Scala DSLs
Scala’s implicits
Real-World Scala Design Patterns
Scala Implicits - Not to be feared
Clustering Java applications with Terracotta and Hazelcast
Variance in scala
Types by Adform Research, Saulius Valatka
Ad

Similar to So various polymorphism in Scala (20)

PDF
Scala in Places API
PDF
A Sceptical Guide to Functional Programming
PPTX
Intro to scala
ODP
Ast transformations
PPTX
A (too) Short Introduction to Scala
PDF
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
PDF
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
PDF
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
PDF
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
ODP
Beginning Scala Svcc 2009
PPT
Scala - brief intro
ODP
Groovy Ast Transformations (greach)
PDF
TI1220 Lecture 8: Traits & Type Parameterization
PDF
Revisiting SOLID Principles
PDF
Scala - en bedre og mere effektiv Java?
PDF
The Scala Programming Language
PDF
Scala Intro
PDF
アプリを弄ってみる #1 #antama_ws
PPTX
Thinking Functionally with JavaScript
PDF
Genomic Analysis in Scala
Scala in Places API
A Sceptical Guide to Functional Programming
Intro to scala
Ast transformations
A (too) Short Introduction to Scala
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
pragmaticrealworldscalajfokus2009-1233251076441384-2.pdf
Beginning Scala Svcc 2009
Scala - brief intro
Groovy Ast Transformations (greach)
TI1220 Lecture 8: Traits & Type Parameterization
Revisiting SOLID Principles
Scala - en bedre og mere effektiv Java?
The Scala Programming Language
Scala Intro
アプリを弄ってみる #1 #antama_ws
Thinking Functionally with JavaScript
Genomic Analysis in Scala

More from b0ris_1 (8)

PDF
Learning from nature or human body as a source on inspiration for software en...
PDF
Devoxx 2022
PDF
IT Arena-2021
PDF
New accelerators in Big Data - Upsolver
PDF
Learning from nature [slides from Software Architecture meetup]
PDF
Cowboy dating with big data TechDays at Lohika-2020
PDF
Cowboy dating with big data
PDF
Ultimate journey towards realtime data platform with 2.5M events per sec
Learning from nature or human body as a source on inspiration for software en...
Devoxx 2022
IT Arena-2021
New accelerators in Big Data - Upsolver
Learning from nature [slides from Software Architecture meetup]
Cowboy dating with big data TechDays at Lohika-2020
Cowboy dating with big data
Ultimate journey towards realtime data platform with 2.5M events per sec

Recently uploaded (20)

PPTX
L1 - Introduction to python Backend.pptx
PDF
Audit Checklist Design Aligning with ISO, IATF, and Industry Standards — Omne...
PDF
Internet Downloader Manager (IDM) Crack 6.42 Build 41
PPTX
CHAPTER 2 - PM Management and IT Context
PDF
Adobe Illustrator 28.6 Crack My Vision of Vector Design
PPTX
Odoo POS Development Services by CandidRoot Solutions
PDF
Claude Code: Everyone is a 10x Developer - A Comprehensive AI-Powered CLI Tool
PPTX
Reimagine Home Health with the Power of Agentic AI​
PDF
How to Choose the Right IT Partner for Your Business in Malaysia
PPTX
Operating system designcfffgfgggggggvggggggggg
PDF
top salesforce developer skills in 2025.pdf
PDF
Understanding Forklifts - TECH EHS Solution
PDF
Why TechBuilder is the Future of Pickup and Delivery App Development (1).pdf
PDF
Adobe Premiere Pro 2025 (v24.5.0.057) Crack free
PDF
Design an Analysis of Algorithms I-SECS-1021-03
PDF
Addressing The Cult of Project Management Tools-Why Disconnected Work is Hold...
PPTX
Essential Infomation Tech presentation.pptx
PDF
wealthsignaloriginal-com-DS-text-... (1).pdf
PPTX
Transform Your Business with a Software ERP System
PDF
Flood Susceptibility Mapping Using Image-Based 2D-CNN Deep Learnin. Overview ...
L1 - Introduction to python Backend.pptx
Audit Checklist Design Aligning with ISO, IATF, and Industry Standards — Omne...
Internet Downloader Manager (IDM) Crack 6.42 Build 41
CHAPTER 2 - PM Management and IT Context
Adobe Illustrator 28.6 Crack My Vision of Vector Design
Odoo POS Development Services by CandidRoot Solutions
Claude Code: Everyone is a 10x Developer - A Comprehensive AI-Powered CLI Tool
Reimagine Home Health with the Power of Agentic AI​
How to Choose the Right IT Partner for Your Business in Malaysia
Operating system designcfffgfgggggggvggggggggg
top salesforce developer skills in 2025.pdf
Understanding Forklifts - TECH EHS Solution
Why TechBuilder is the Future of Pickup and Delivery App Development (1).pdf
Adobe Premiere Pro 2025 (v24.5.0.057) Crack free
Design an Analysis of Algorithms I-SECS-1021-03
Addressing The Cult of Project Management Tools-Why Disconnected Work is Hold...
Essential Infomation Tech presentation.pptx
wealthsignaloriginal-com-DS-text-... (1).pdf
Transform Your Business with a Software ERP System
Flood Susceptibility Mapping Using Image-Based 2D-CNN Deep Learnin. Overview ...

So various polymorphism in Scala

  • 1. SO VARIOUS POLYMORPHISM IN SCALA Boris Trofimov @ Sigma Software @b0ris_1
  • 4. WHY SCALA CONTEXT MAP POLYMORPHISM DEFINITION BASIC DEGREE BACHELOR DEGREE MAST DEGR AGENDA  Object-Oriented Meets Functional  Strongly Functional  It makes you love your code again  Scalable grammar  Hello Domain Specific Languages (DSL)  Inexhaustible language for every day
  • 5. SCALA JAVA class A (p: String) class A { final String p; public A(String p) { this.p = p; } } val variable = "string" final String variable = "string" ; def func (p: String): String = {...} String func (String p) { ... } trait A { def run() } interface A { void run() ; } сlass A[B <: C] { … } class A <B extends C> { ... } object A { … } Class - Singleton definition CONTEXT MAP POLYMORPHISM DEFINITION BASIC DEGREE BACHELOR DEGREE MAST DEGR CONTEXT MAP WHY SCALA AGENDA
  • 6. CONTEXT MAP POLYMORPHISM DEFINITION BASIC DEGREE BACHELOR DEGREE MAST DEGR POLYMORPHISM DEFINITION WHY SCALA AGENDA  Ability of language to handle data of different types in the same way.  Provision of a single interface to entities of different types.  Particular code is able to handle data of different types.  Way to change code behavior via input parameters without direct modification (respecting Open-Closed Principle) Polymorphic code will be highlighted in a frame
  • 8. AD-HOC SUBTYPING PARAMETRIC POLYMORPHISM REFLECTION SUBTYPING FUNCTIONAL SUBTYPING abstract class A{ def method() { ... this.doSomething ... } // abstract method def doSomething } class B extends A{ override def doSomething { … } } class B extends C{ override def doSomething { … } }
  • 9. AD-HOC SUBTYPING PARAMETRIC POLYMORPHISM REFLECTION SUBTYPING FUNCTIONAL SUBTYPING trait A class B extends A class C extends A class List { def add(a : A) = { ... } } SUBTYPINGAD-HOC
  • 10. AD-HOC SUBTYPING PARAMETRIC POLYMORPHISM REFLECTION SUBTYPING FUNCTIONAL SUBTYPING AD-HOC class MyClass { def addItem[A](a: A): List[A] = { val list = new ListBuffer[A] list += a list.toList() } // B should be inheritor of ParentClass def addItem[B <: ParentClass] (b: B) : List[A] = { val list = new ListBuffer[B] list += b list.toList() } } PARAMETRIC POLYMORPHISM
  • 11. AD-HOC SUBTYPING PARAMETRIC POLYMORPHISM REFLECTION SUBTYPING FUNCTIONAL SUBTYPING AD-HOC REFLECTION SUBTYPING class MyClass { def doSomething(a: Object) = { ... val method = a.getClass().getMethod("run", Int) method.invoke(a, 1) ... } }
  • 12. AD-HOC SUBTYPING PARAMETRIC POLYMORPHISM REFLECTION SUBTYPING FUNCTIONAL SUBTYPING AD-HOC FUNCTIONAL SUBTYPING class List[A] { ... def sort(data : (A, A) => Int ) : List[A] = { ... } } object Application extends App{ val list = List(7,8,5,4) list.sort( (a,b) => a – b ) // _-_ }
  • 14. DUCK SUBTYPING CAKE PATTERN CHAINING POLYMORPHISM When I see a bird that walks like a duck and swims like a duck and quacks like a duck, I call that bird a duck class MyClass { def doSomething(a : type { def run(i : Int) } ) = { ... a.run(1) ... } } class DuckClass { def run(i : Int) { ... } } new MyClass().doSomething( new DuckClass() ) Caution: Reflection!
  • 15. CAKE PATTERN CHAINING POLYMORPHISM DUCK SUBTIPING CAKE PATTERN trait ComponentA { def doThis() : String } trait ComponentB { def doThat() : String } class OurComponent extends ComponentA with ComponentB { def doSomething() = doThis() + doThat() }
  • 16. CAKE PATTERN CHAINING POLYMORPHISM DUCK SUBTIPING CAKE PATTERN trait ComponentA { def doThis() : String } trait ComponentB { def doThat() : String } class OurComponent extends ComponentA with ComponentB { def doSomething() = doThis() + doThat() } trait ComponentAImpl extends ComponentA { def doThis() = "hello Component A" } trait ComponentBImpl extends ComponentB { def doThat() = "hello Component B" }
  • 17. CAKE PATTERN CHAINING POLYMORPHISM DUCK SUBTIPING CAKE PATTERN trait ComponentA { def doThis() : String } trait ComponentB { def doThat() : String } class OurComponent extends ComponentA with ComponentB { def doSomething() = doThis() + doThat() } trait ComponentAImpl extends ComponentA { def doThis() = "hello Component A" } trait ComponentBImpl extends ComponentB { def doThat() = "hello Component B" } object Main extends App{ val obj = new OurComponent with ComponentAImpl with ComponentBImpl println( obj.doSomething() ) }
  • 18. CAKE PATTERN CHAINING POLYMORPHISM DUCK SUBTIPING CHAINING POLYMORPHISM trait AbstractOperation { def run() } class SaveToDataBaseOperation extends AbstractOperation { override def run(): Unit = { println("Save it to database") } }
  • 19. CAKE PATTERN CHAINING POLYMORPHISM DUCK SUBTIPING CHAINING POLYMORPHISM trait AbstractOperation { def run() } class SaveToDataBaseOperation extends AbstractOperation { override def run(): Unit = { println("Save it to database") } } // decorating with audit trait AuditDecorator extends AbstractOperation { abstract override def run(): Unit = { println("Entering AuditDecorator") super.run() println("Leaving AuditDecorator") } } // decorating with caching trait CachingDecorator extends AbstractOperation { abstract override def run(): Unit = { println("Caching something") super.run() } }
  • 20. CAKE PATTERN CHAINING POLYMORPHISM DUCK SUBTIPING CHAINING POLYMORPHISM trait AbstractOperation { def run() } class SaveToDataBaseOperation extends AbstractOperation { override def run(): Unit = { println("Save it to database") } } // decorating with audit trait AuditDecorator extends AbstractOperation { abstract override def run(): Unit = { println("Entering AuditDecorator") super.run() println("Leaving AuditDecorator") } } // decorating with caching trait CachingDecorator extends AbstractOperation { abstract override def run(): Unit = { println("Caching something") super.run() } } object MyApp extends App { val operation = new SaveToDataBaseOperation with CachingDecorator with AuditDecorator operation.run() } OUTPUT: >Entering AuditDecorator >Caching something >Save it to database >Leaving AuditDecorator
  • 22. TYPE CLASSES RETROACTIVE POLYMORPHISM IMPLICIT DI TYPE CONSTRUCTORS object Test{ println( Arithmetics.add("Hello", " World") ) // returns “Hello World” println( Arithmetics.add(2,3) ) // returns 5 // Compile Error, could not find corresponding implicit object println( Arithmetics.add(123.0, -45.345) ) } F-BOUNDED POLYMORPHISM
  • 23. TYPE CLASSES RETROACTIVE POLYMORPHISM IMPLICIT DI TYPE CONSTRUCTORS object Test{ println( Arithmetics.add("Hello", " World") ) // returns “Hello World” println( Arithmetics.add(2,3) ) // returns 5 // Compile Error, could not find corresponding implicit object println( Arithmetics.add(123.0, -45.345) ) } trait NumericLike[T] { def plus(x : T, y: T) : T } implicit object TInteger extends NumericLike[Int]{ def plus(x : Int, y: Int) : Int = x + y } implicit object TString extends NumericLike[String]{ def plus(x : String, y: String) : String = x + y } object Arithmetics{ // generalized `add` method def add[T : NumericLike](x:T, y:T): T = { val engine = implicitly[NumericLike[T]] engine.plus(x, y) } } Type Class Pattern F-BOUNDED POLYMORPHISM Type Class can be treated as an advocate for specific type T
  • 24. TYPE CLASSES RETROACTIVE POLYMORPHISM IMPLICIT DI TYPE CONSTRUCTORS F-BOUNDED POLYMORPHISM RETROACTIVE POLYMORPHISM TYPE CLASSES https://github.com/spray/spray-json import spray.json._ import DefaultJsonProtocol._ // from json val source = """{ "some": ["JSON source"] }""" val ast = source.parseJson val myObject = ast.convertTo[Map[String, Array[String]]] // to json val jsonAst = Map(Array("1"), Array("1")).toJson // to ast val json = jsonAst.prettyPrint // or .compactPrint class Color(val name: String, val red: Int, val green: Int, val blue: Int) // custom serializer via type class object MyJsonProtocol extends DefaultJsonProtocol { implicit object ColorJsonFormat extends RootJsonFormat[Color] { def write(c: Color) = . . . def read(value: JsValue) = ... } } import MyJsonProtocol._ val json = Color("CadetBlue", 95, 158, 160).toJson val color = json.convertTo[Color] The ability to extend functionality of a library without modifying its source is known as Retroactive Extension
  • 25. TYPE CLASSES RETROACTIVE POLYMORPHISM IMPLICIT DI TYPE CONSTRUCTORS F-BOUNDED POLYMORPHISM IMPLICIT DI RETROACTIVE POLYMORPHISM trait Future[+T] extends Awaitable[T] { … def filter(pred: T => Boolean) (implicit executor: ExecutionContext): Future[T] = map { r => if (pred(r)) r else throw new NoSuchElementException("Future.filter predicate is not satisfied") } def map[S](f: T => S) (implicit executor: ExecutionContext): Future[S] = { // transform(f, identity) val p = Promise[S]() onComplete { v => p complete (v map f) } p.future } } TYPE CLASSES Dependency Injection per method
  • 26. TYPE CLASSES RETROACTIVE POLYMORPHISM IMPLICIT DI TYPE CONSTRUCTORS F-BOUNDED POLYMORPHISM IMPLICIT DI RETROACTIVE POLYMORPHISM trait Future[+T] extends Awaitable[T] { … def filter(pred: T => Boolean) (implicit executor: ExecutionContext): Future[T] = map { r => if (pred(r)) r else throw new NoSuchElementException("Future.filter predicate is not satisfied") } def map[S](f: T => S) (implicit executor: ExecutionContext): Future[S] = { // transform(f, identity) val p = Promise[S]() onComplete { v => p complete (v map f) } p.future } } ... import scala.concurrent.ExecutionContext.Implicits.global val future = Future { 12345 }. map { x => x + 1} // _ + 1 TYPE CLASSES Dependency Injection per method
  • 27. TYPE CLASSES RETROACTIVE POLYMORPHISM IMPLICIT DI TYPE CONSTRUCTORS F-BOUNDED POLYMORPHISM IMPLICIT DI RETROACTIVE POLYMORPHISM trait Future[+T] extends Awaitable[T] { … def filter(pred: T => Boolean) (implicit executor: ExecutionContext): Future[T] = map { r => if (pred(r)) r else throw new NoSuchElementException("Future.filter predicate is not satisfied") } def map[S](f: T => S) (implicit executor: ExecutionContext): Future[S] = { // transform(f, identity) val p = Promise[S]() onComplete { v => p complete (v map f) } p.future } } ... import scala.concurrent.ExecutionContext.Implicits.global val future = Future { 12345 }. map { x => x + 1} // _ + 1 // test code implicit val executionContext = mock[ExecutionContext] val future = Future { 12345 }. map { _ + 1} TYPE CLASSES Dependency Injection per method
  • 28. TYPE CLASSES RETROACTIVE POLYMORPHISM IMPLICIT DI TYPE CONSTRUCTORS F-BOUNDED POLYMORPHISM TYPE CONSTRUCTORS TYPE CLASSES More about motivation and examples http://adriaanm.github.io/files/higher.pdf Way to build generalized types to take generics as a parameter
  • 29. TYPE CLASSES RETROACTIVE POLYMORPHISM IMPLICIT DI TYPE CONSTRUCTORS F-BOUNDED POLYMORPHISM TYPE CONSTRUCTORS TYPE CLASSES object Test{ Operations.tupleize(Some(1), Some(2)) // returns Some( (1,2) ) Operations.tupleize(List(1,3), List (2,4)) //returns List( (1,2) , (3,4) ) }
  • 30. TYPE CLASSES RETROACTIVE POLYMORPHISM IMPLICIT DI TYPE CONSTRUCTORS F-BOUNDED POLYMORPHISM TYPE CONSTRUCTORS TYPE CLASSES object Test{ Operations.tupleize(Some(1), Some(2)) // returns Some( (1,2) ) Operations.tupleize(List(1,3), List (2,4)) //returns List( (1,2) , (3,4) ) } trait ContainerHandler[M[_]] { def put[A](x: A): M[A] def get[A](m: M[A]): A } object Operations{ def tupleize[M[_]: ContainerHandler, A, B](fst: M[A], snd: M[B]) = { val engine = implicitly[ContainerHandler[M]] engine.put( Pair(engine.get(fst), engine.get(snd)) ) } }
  • 31. TYPE CLASSES RETROACTIVE POLYMORPHISM IMPLICIT DI TYPE CONSTRUCTORS F-BOUNDED POLYMORPHISM TYPE CONSTRUCTORS TYPE CLASSES object Test{ Operations.tupleize(Some(1), Some(2)) // returns Some( (1,2) ) Operations.tupleize(List(1,3), List (2,4)) //returns List( (1,2) , (3,4) ) } trait ContainerHandler[M[_]] { def put[A](x: A): M[A] def get[A](m: M[A]): A } object Operations{ def tupleize[M[_]: ContainerHandler, A, B](fst: M[A], snd: M[B]) = { val engine = implicitly[ContainerHandler[M]] engine.put( Pair(engine.get(fst), engine.get(snd)) ) } } implicit val listHandler = new ContainerHandler[List]{ def put[A](x: A) = List(x); def get[A](m: List[A]) = m.head } implicit val optionHandler = new ContainerHandler[Some]{ def put[A](x: A) = Some(x); def get[A](m: Some[A]) = m.get }
  • 32. trait Account[T <: Account[T] ] { def addFunds(amount: BigDecimal): T } class CheckingAccount(total: BigDecimal, trxMaxCount: Int) extends Account[CheckingAccount] { def addFunds(amount: BigDecimal) : CheckingAccount = new CheckingAccount(total + amount, trxMaxCount) } class SavingAccount(total: BigDecimal) extends Account[SavingAccount] { def addFunds(amount: BigDecimal) : SavingAccount = new SavingAccount(total + amount) } TYPE CLASSES RETROACTIVE POLYMORPHISM IMPLICIT DI TYPE CONSTRUCTORS F-BOUNDED POLYMORPHISM F-BOUNDED POLYMORPHISM TYPE CLASSES How to define function that, though defined in terms of a supertype, will when passed a value of some subtype will always return a value of the same subtype as its argument? trait Account { def addFunds(amount: BigDecimal): Account //??? }
  • 33. trait Account[T <: Account[T] ] { def addFunds(amount: BigDecimal): T } class CheckingAccount(total: BigDecimal, trxMaxCount: Int) extends Account[CheckingAccount] { def addFunds(amount: BigDecimal) : CheckingAccount = new CheckingAccount(total + amount, trxMaxCount) } class SavingAccount(total: BigDecimal) extends Account[SavingAccount] { def addFunds(amount: BigDecimal) : SavingAccount = new SavingAccount(total + amount) } TYPE CLASSES RETROACTIVE POLYMORPHISM IMPLICIT DI TYPE CONSTRUCTORS F-BOUNDED POLYMORPHISM F-BOUNDED POLYMORPHISM TYPE CLASSES How to define function that, though defined in terms of a supertype, will when passed a value of some subtype will always return a value of the same subtype as its argument? trait Account { def addFunds(amount: BigDecimal): Account //??? }
  • 34. TYPE CLASSES RETROACTIVE POLYMORPHISM IMPLICIT DI TYPE CONSTRUCTORS F-BOUNDED POLYMORPHISM F-BOUNDED POLYMORPHISM TYPE CLASSES object Account { val feePercentage = BigDecimal("0.02") val feeThreshold = BigDecimal("10000.00") def deposit[T <: Account[T]](amount: BigDecimal, account: T): T = { if (amount < feeThreshold) account.addFunds(amount - (amount * feePercentage)) else account.addFunds(amount) } http://logji.blogspot.com/2012/11/f-bounded-type-polymorphism-give-up-now.html
  • 35. TYPE CLASSES RETROACTIVE POLYMORPHISM IMPLICIT DI TYPE CONSTRUCTORS F-BOUNDED POLYMORPHISM F-BOUNDED POLYMORPHISM TYPE CLASSES object Account { val feePercentage = BigDecimal("0.02") val feeThreshold = BigDecimal("10000.00") def deposit[T <: Account[T]](amount: BigDecimal, account: T): T = { if (amount < feeThreshold) account.addFunds(amount - (amount * feePercentage)) else account.addFunds(amount) } def debitAll(amount: BigDecimal, accounts: List[T forSome { type T <: Account[T] }]): List[T forSome { type T <: Account[T] }] = { accounts map { _.addFunds(-amount) } } } object Test { val list = List[T forSome { type T <: Account[T] }]( new CheckingAccount(BigDecimal("0"), 10), new SavingAccount(BigDecimal("0"))) Account.debitAll(BigDecimal("10.00"), list) } The second frame uses trick with existential types to store in one collection http://logji.blogspot.com/2012/11/f-bounded-type-polymorphism-give-up-now.html
  • 36. Scala Puzzle def gen2(i: Int): Stream[Int] = Stream(i) append gen2(i+1) println(gen2(0).take(10).to[List]) // > List(0, 1, 2, 3, 4, 5, 6, 7, 8, 9) def gen(i: Int): Stream[Int] = Stream(i) ++ gen(i+1) println(gen(0).take(10).to[List]) // > List(0, 1, 2, 3, 4, 5, 6, 7, 8, 9) (2) The first fails, the second succeeds (1) Both will fail with StackOverflowError (4) The second fails, the first succeeds (3) Both will succeed 1 2
  • 38. TYPE CLASSES POLYMORPHIC FUNCTIONS RETROACTIVE POLYMORPHISM We treat type aliases like abstract virtual functions passing and returning types, for instance: def Prev : Nat def Plus(A: Nat) : Nat VIRTUAL TYPES object Factorial extends App { trait Nat { type Prev <: Nat type Plus[A <: Nat] <: Nat type Times[A <: Nat] <: Nat type Factorial <: Nat } trait _0 extends Nat { type Prev = _0 type Plus[A <: Nat] = A type Times[A <: Nat] = _0 type Factorial = _1 } trait Succ[N <: Nat] extends Nat { type This = Succ[N] type Prev = N type Times[A <: Nat] = A#Plus[N#Times[A]] type Plus[A <: Nat] = N#Plus[Succ[A]] type Factorial = This#Times[Prev#Factorial] } type _1 = Succ[_0] type _2 = Succ[_1] type _3 = Succ[_2] type _4 = Succ[_3] type _5 = Succ[_4] type _6 = Succ[_5] type _7 = Succ[_6] type _8 = Succ[_7] type _9 = Succ[_8] // Calculate 3! = 6 implicitly[_3#Factorial =:= _6] } https://gist.github.com/mkleen/9290750
  • 39. TYPE CLASSES POLYMORPHIC FUNCTIONS VIRTUAL TYPES POLYMORPHIC FUNCTIONS https://github.com/milessabin/shapeless/wiki/Feature-overview:-shapeless-2.0.0  Scala function values are monomorphic due to interface Function1[U,V] { .. }  Shapeless library allows to avoid this limitation  Polymorphic functions allow to process heterogeneous collections (HLists) import poly._ // choose is a function from Sets to Options with no type specific cases object choose extends (Set ~> Option) { def apply[T](s : Set[T]) = s.headOption } scala> choose(Set(1, 2, 3)) res0: Option[Int] = Some(1) scala> choose(Set('a', 'b', 'c')) res1: Option[Char] = Some(a) scala> val sets = Set(1) :: Set("foo") :: HNil scala> val opts = sets map choose // map selects cases of choose for each HList element opts: Option[Int] :: Option[String] :: HNil = Some(1) :: Some(foo) :: HNil Define polymorphic function
  • 40. TYPE CLASSES POLYMORPHIC FUNCTIONS VIRTUAL TYPES POLYMORPHIC FUNCTIONS https://github.com/milessabin/shapeless/wiki/Feature-overview:-shapeless-2.0.0  Scala function values are monomorphic due to interface Function1[U,V] { .. }  Shapeless library allows to avoid this limitation  Polymorphic functions allow to process heterogeneous collections (HLists) import poly._ // choose is a function from Sets to Options with no type specific cases object choose extends (Set ~> Option) { def apply[T](s : Set[T]) = s.headOption } scala> choose(Set(1, 2, 3)) res0: Option[Int] = Some(1) scala> choose(Set('a', 'b', 'c')) res1: Option[Char] = Some(a) scala> val sets = Set(1) :: Set("foo") :: HNil scala> val opts = sets map choose // map selects cases of choose for each HList element opts: Option[Int] :: Option[String] :: HNil = Some(1) :: Some(foo) :: HNil It behaves like an usual function Define polymorphic function
  • 41. TYPE CLASSES POLYMORPHIC FUNCTIONS VIRTUAL TYPES POLYMORPHIC FUNCTIONS https://github.com/milessabin/shapeless/wiki/Feature-overview:-shapeless-2.0.0  Scala function values are monomorphic due to interface Function1[U,V] { .. }  Shapeless library allows to avoid this limitation  Polymorphic functions allow to process heterogeneous collections (HLists) import poly._ // choose is a function from Sets to Options with no type specific cases object choose extends (Set ~> Option) { def apply[T](s : Set[T]) = s.headOption } scala> choose(Set(1, 2, 3)) res0: Option[Int] = Some(1) scala> choose(Set('a', 'b', 'c')) res1: Option[Char] = Some(a) scala> val sets = Set(1) :: Set("foo") :: HNil scala> val opts = sets map choose // map selects cases of choose for each HList element opts: Option[Int] :: Option[String] :: HNil = Some(1) :: Some(foo) :: HNil HList runs polymorphic function It behaves like an usual function Define polymorphic function
  • 42. REFERENCES  http://adriaanm.github.io/files/higher.pdf  http://twitter.github.io/scala_school/advanced-types.html  http://logji.blogspot.com/2012/11/f-bounded-type-polymorphism-give-up- now.html  http://danielwestheide.com/blog/2013/02/06/the-neophytes-guide-to-scala- part-12-type-classes.html  https://gist.github.com/mkleen/9290750  http://apocalisp.wordpress.com/2010/06/08/type-level-programming-in- scala/