so different polymorphism in scala

23
So different polymorphism in Scala Boris Trofimov @b0ris_1 www.btrofimoff.com

Upload: b0ris1

Post on 27-Aug-2014

1.375 views

Category:

Software


6 download

DESCRIPTION

Scala has at least 9 types of polymorphism. Do not believe? Let's dig in.

TRANSCRIPT

Page 1: So different polymorphism in Scala

So different polymorphism

in Scala

Boris Trofimov

@b0ris_1

www.btrofimoff.com

Page 2: So different polymorphism in Scala

Scala has at least 9 kinds of

polymorphism

Don’t believe?

Let’s dig in

Page 3: So different polymorphism in Scala

Agenda

Why Scala?

A few words about definition

Classic polymorphism

Parametric polymorphism

Reflection polymorphism

Functional polymorphism

Duck polymorphism

Enhanced Ad-hoc polymorphism

Type class polymorphism

Parametric polymorphism of the 2nd kind

F-bounded polymorphism

Page 4: So different polymorphism in Scala

Why Scala?

Object-Oriented Meets Functional

Strong Functional

It makes you love your code again

Scalable grammar

Hello Domain Specific Languages (DSL)

Inexhaustible language for every day

Page 5: So different polymorphism in Scala

Basic Degree

Page 6: So different polymorphism in Scala

Definition

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

modifications

Page 7: So different polymorphism in Scala

Classic polymorphism

Ad-hoc

Subtyping

class A{

def method {

...

this.doSomething

...

}

// abstract method

def doSomething

}

class B extends A{

override def doSomething {}

}

class B extends C{

override def doSomething {}

}

class A

class B extends A

class C extends A

class List{

def add(a : A) {

...

}

}

Page 8: So different polymorphism in Scala

Parametric polymorphism

class MyClass{

def addItem[A](a:A) = {

val list = new ListBuffer[A]

list +=a

list

}

def addItem[B <: ParentClass] (b:B) = {

val list = new ListBuffer[B]

list +=b

list

}

}

Page 9: So different polymorphism in Scala

Reflection polymorphism (ugly version)

class MyClass{

def doSomething(a: Object){

...

val method = a.getClass().getMethod(“run”, Int);

method.invoke(a, 1);

...

}

}

Page 10: So different polymorphism in Scala

Functional polymorphism

class A ( sortFunc: List[Int] => List[Int] ){

def doSomething(data : List[Int]) = {

...

sortFunc(data)

...

}

}

object BubbleSort{

def sort(a:List[Int]) : List[Int] = { ... }

}

object QuickSort{

def sort(a:List[Int]) : List[Int] = { ... }

}

object Application{

def main(){

val a = new A(BubbleSort.sort(_))

a.doSomething(List(1,2,3))

}

}

object Sorter{

def sort( list : List[Int],

data : (Int,Int) => Int ) : List[Int] = {

...

}

}

object Application{

def main(){

val list = List(7,8,5,4)

Sorter.sort(list, (a,b) => a-b)

}

}

Page 11: So different polymorphism in Scala

Hello Scala

or Bachelor degree

Page 12: So different polymorphism in Scala

Duck 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

Scala structural types

Caution: Reflection!

class MyClass{

def doSomething(a : type { def run(i : Int) } ){

...

a.run(1)

...

}

}

class DuckClass {

def run(i : Int) {

...

}

}

Page 13: So different polymorphism in Scala

Type constructor polymorphism

trait ParentTrait{

type T

type MapperType =

com.apache.hadoop.Mapper[LongWritable,Text,AvroKey[CharSequence],AvroValue[T]]

type Context = MapperType#Context

...

}

object CustomMapperObject extends ParentTrait{

type T = Pair[String,String]

class CustomMapper extends MapperType {

override def setup(context:Context) = {

...

}

override def map(key:LongWritable, value:Text, context:Context) = {

...

}

}

}

Type variables defined in sibling classes

Building another types dependent on type variables

Page 14: So different polymorphism in Scala

Enhanced Ad-hoc polymorphism -Intro

Inheritance vs Composition

Mixin pattern – a way to inject

some code into class impl.

Scala supports Mixin (Trait)

Trait – is like interface +

implementation with multiple

trait inheritance and without

head pain

trait Utils{

def printList[A](list: List[A]) =

list.foreach (a => System.Console.println(a))

}

trait LogTrait {

lazy val logger =

LoggerFactory.getLogger(this.getClass.getName)

def setLogLevel(level : Level) =

Logger.getRootLogger.setLevel(level)

}

class MyClass extends LogTrait with Utils{

def do(){

logger.info("hello world!");

printList List(1,2,3,4,5,6)

}

}

Page 15: So different polymorphism in Scala

Enhanced Ad-hoc polymorphism – Continue

or welcome to 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 {

def main() {

val obj = new OurComponent with ComponentAImpl with ComponentBImpl

println(obj.doSomething())

}

}

Page 16: So different polymorphism in Scala

Master degree

Page 17: So different polymorphism in Scala

Type class polymorphism – Intro Way to create generalized methods with partial specialization

Way to have some logic which cannot be added to origin class T (for

instance tricky serialization)

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](x:T, y:T)(implicit engine : NumericLike[T]) = engine.plus(x, y)

}

object Test{

println( Arithmetics.add("Hello", " World") ) // returns HelloWorld

println( Arithmetics.add(2,3) ) // returns 5

// Compile Error, could not find corresponding implicit object

println( Arithmetics.add(123.0, -45.345) )

}

Page 18: So different polymorphism in Scala

Type class polymorphism – Continue

or inventing DI class ComponentA{

...

}

class ComponentB{

...

}

class ComponentC (implicit componentA: ComponentA, componentB: ComponentB){

...

}

object LiveContext{

implicit val componentA = new ComponentA()

implicit val componentB = new ComponentB()

implicit val componentC = new ComponentC()

}

object TestContext{

implicit val componentA = mock[ComponentA]

implicit val componentB = mock[ComponentB]

implicit val componentC = new ComponentC()

}

Page 19: So different polymorphism in Scala

Parametric polymorphism of the 2nd kind

Way to build generalized types to take generics as parameters

trait ContainerHandler[M[_]] {

def put[A](x: A): M[A]

def get[A](m: M[A]): A

}

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 }

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)) )

}

}

object Test{

Operations.tupleize(Some(1), Some(2)) // returns Some( (1,2) )

Operations.tupleize(List(1), List (2)) //returns List( (1,2) )

}

Page 20: So different polymorphism in Scala

trait Ordered[T]{

def compare(that: T): Int

}

class MyContainer extends Ordered[MyContainer] {

def compare(that: MyContainer): Int = { ... }

}

F-bounded polymorphism – Intro

How to define a polymorphic function that, though defined in terms of

a supertype, will when passed a value of some subtype will always

return/take a value of the same subtype as its argument.

Simplest example:

F-bounded polymorphism plus existential types allows building

generalized functions which process collections of different types(!)

Page 21: So different polymorphism in Scala

F-bounded polymorphism – Continue 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)

}

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 {

def main(argv: Array[String]): Unit = {

Account.debitAll(BigDecimal("10.00"),

List[T forSome { type T <: Account[T] }](

new CheckingAccount(BigDecimal("0"), 10), new SavingAccount(BigDecimal("0"))))

}

}

Page 22: So different polymorphism in Scala

Referencies

Martin Odersky Programming in Scala

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

Page 23: So different polymorphism in Scala

Thank you!

Q&A