## How to bepolymorphic in Scala

### Polymorhism

is a programming language feature that allows one interface to be used for a general class of actions. John C. Reynolds. Theories of programming languages. Cambridge University Press, New York, NY, USA, 1999.

# Parametric

### Parametric (type as parameter)

defined on functions or a data types so that they can be written generically and it can handle values identically without depending on their type.

``````
class Container[A](val value : A) {              // Type-constructor
def map[B](f : A => B): Container[B] =
new Container(f(value))
}

new Container(10) map { x => (x * 2).toString } // Container(“20”)
new Container("10") map { x => x.toInt * 2 }    // Container(20)
``````

### Higher-kinded (ranked) polymorphism

Kind is the type of a type-constructor (type of of a higher-order type operator).

• #### Value level:

``````
val x : String
val y : List[String]

def id(x : Int):Int = x
def map(f : Int=> Int, x: Int) = f(x)
``````
• #### Type level:

``````
type String     :: *
type List       :: * -> *
type Function1  :: * -> * -> *

type Id[A] = A
type Map[C[_],A] = C[A]
``````

### Higher-kinded (ranked) polymorphism

• Kind systems classify types
• Values are to types as types are to kinds
• “Higher” kinds are the kinds of type constructors

• #### Predicative polymorphism:

``````
trait ~>[T[_],R[_]] {  // T & R - have predicates [_]
def apply[A](a : T[A]): R[A]
}

val naturalTransformation = new (List ~> Option) { //  ~>[List, Option]
def apply[A](a : List[A]): Option[A] = a.headOption
}
``````

### Declaration-Site Variance

way of propagation types relation rules to type constructor relation rules.

 Meaning Scala notation Covariant C[T’] is a subclass of C[T] [+T] Contravariant C[T] is a subclass of C[T’] [-T] Invariant C[T] and C[T’] are not related [T]

### Declaration-Site Variance

way of propagation types relation rules to type constructor relation rules.

• • • • ### Using-Site Variance

by using upper and lower bounds notations.

• #### For types:

``````
case class Employee(name: String)
case class Developer(yearsOfExperince: Int)
// and container:
class Foo[T]
``````
• #### Using-Site Covariance:

``````
def apply(a : Foo[_ <: Employee]): String
// or by existential type declaration:
def apply(a: Foo[X] forSome { type X <: Employee}): String
``````
• #### Using-Site Contravariance:

``````
def apply[A](a: Foo[_ >: Employee]): String
// or by existential type declaration:
def apply(a : Foo[X] forSome { type X >: Employee}): String
``````

# Inclusion

### Inclusion (Inheritance and Subtyping)

is a form of type polymorphism in which a subtype is a data-type that is related to another data-type (the super-type) by some notion of substitutability.

• #### Subtype polymorphism:

``````
class Animal
trait Furry extends Animal
trait HasLegs extends Animal
trait FourLegged extends Animal with HasLegs
class Cat extends Animal with Furry with FourLegged

val cat = new Cat()
``````

### Traits in Scala

#### 1. “Rich Interface” role:

``````
trait RichIterable[A] {
def iterator : java.util.Iterator[A]  // contract method

def foreach(f : A => Unit) = {
val iter = iterator
while (iter.hasNext) f(iter.next)
}

def foldLeft[B](seed : B)(f : (B, A) => B) = {
var result = seed
foreach(e => result = f(result, e))
result
}
}

val richSet =
new java.util.HashSet[Int]
with RichIterable[Int]

richSet.foldLeft(0)((x, y) => x + y)  // == 3
``````

#### 2. “Stackable modification” role:

``````
trait IgnoreCaseSet extends java.util.Set[String] {
abstract override def add(e : String) = {
}

abstract override def contains(e: Object) = {
e match {
case s: String  => super.contains(s.toLowerCase)
case o          => super.contains(o)
}
}
}

val set =
new java.util.HashSet[String]
with IgnoreCaseSet

set.contains("hi there")  // lowercase
``````

#### 3. “Multiple View” role:

``````
//Facets
trait Entity { ... }
trait InventoryItemSet { ... }
trait PurchaseLimiter { ... }
trait MailNotifier { ... }
trait Versioned { ... }
trait Transactional { ... }

// Composition
val order = new Order(customer)
with Entity
with InventoryItemSet
with PurchaseLimiter
with MailNotifier
with Versioned
with Transactional
``````

allows creating several methods with the same name which differ from each other in the type of the input and the output of the function.

``````
case class Complex(re : Double, im : Double) {
def + (another : Complex) =
new Complex(re + another.re, im + another.im)

def unary_- =
new Complex(-re, -im)
}

Complex(2, 5) + Complex(1, -2)  // == Complex(3, 3)
-Complex(1, -2)                 // == Complex(-1, 2)
``````

# Coercion

### Coercion

is the operation of converting an argument or an operand to the type expected by a function or an operator.

#### Coercion by implicit conversions:

``````
case class Complex(re : Double, im : Double) {
def + (another : Complex) =
new Complex(re + another.re, im + another.im)
}

//implicit conversion: a form of coercion
implicit def doubleToComplex(d: Double) = Complex(d, 0)

Complex(2.0, 5.0) + 5.0   // == Complex(7.0, 5.0)
5.0 + Complex(1.0, -2.0)  // == Complex(6.0, -2.0)
``````

### Implicits in Scala

#### 1.1. Implicit Conversion:

• ``````
val str: String = "test - ok"

//C/C++ style condition expression:
if(str) println(str)  //error: type mismatch
``````

• AnyRef to Boolean coversion needed

• ``````
implicit def anyRefIsNotNull(x: AnyRef): Boolean = x != null

//C/C++ style condition expression:
if(str) println(str)  //out: test - ok
``````

#### 1.2. Syntax extension by implicit conversions:

• Ternary operator similar to ? in C/C++:

``````
val res : String = (4*4 > 14) ? "GT" | "LT or EQ"
``````
• Implicit coversion from Boolean to something with ? method:

``````
implicit def boolToOperator(c : Boolean) = new {
def ?[A](t : => A) = new {
def |(f : => A) = if(c) t else f
}
}
``````
• Or:

``````
class MakeIfTrue(b : => Boolean) {
def ?[A](t : => A) = new IfTrue[A](b,t)
}

class IfTrue[A](b : => Boolean, t : => A) {
def |(f : => A) = if (b) t else f
}

implicit def autoMakeIfTrue(b: => Boolean) = new MakeIfTrue(b)
``````

#### 2. Implicit parameters:

``````
def multiplier(i : Int)(implicit factor : Int) {
println(i * factor)
}

implicit val factor = 2

val res1 = multiplier(2)      // res: 4
val res2 = multiplier(2)(3)   // res: 6
``````

# Type-Classes

### Type-Classes

is a type system construct that supports ad hoc polymorphism. This is achieved by adding constraints to type variables in parametrically polymorphic types.

``````
class Show a where
show :: a -> String
``````

• #### In Scala:

``````
trait Show[A] {
def shows(a: A): String
}

trait Show[A] {
def shows : A => String
}            ``````

### Type-Classes

is a type system construct that supports ad hoc polymorphism. This is achieved by adding constraints to type variables in parametrically polymorphic types.

#### Type-classes implementation:

``````
// Type-class Int instance
implicit val IntShow = new Show[Int] {
def shows(a : Int) = a.toString
}

//Type-class List instance:
implicit def ListShow[T] = new Show[List[T]] {
def shows(a : List[T]) = a.mkString(", ")
}
``````

#### Using a Type-classes

``````
def shows[A](a : A)(implicit sh: Show[A]) = sh.shows(a)
//OR:
def shows[A : Show](a : A) = implicitly[Show[A]].shows(a)

// must have a "Show[Int]" instance in scope
shows(42)
``````

### Type-Classes

is a type system construct that supports ad hoc polymorphism. This is achieved by adding constraints to type variables in parametrically polymorphic types.

#### Pimps Type-classes (syntax extension)

``````
trait ShowSyntax[A] {
def shows : String
}

implicit def toShowSyntax[A : Show](a : A)= new ShowSyntax[A] {
def shows = implicitly[Show[A]].shows(a)
}
``````

#### Using a syntax extension

``````
// must have a "Show[Int]" instance in scope
42.shows
``````

### What have we gained?

• We can declare instances outside of the types themselves
• Int knows nothing about Show.
• This is the open world assumption
• In Scala, we can override the typeclass instance by putting a new one in scope:
``````
println(5.shows)    // prints '5‘

localy {
implicit val AltIntShow = new Show[Int] {
def shows(i : Int) = (1 to i) map(_ => "|") mkString
}

println(5.shows)   // prints '|||||'
}
``````