types by adform research

29
Picking up from session 1 OOP/modular named BitSet compound Channel with Logged refined Channel {def close(): Unit } Functional parametrized List[Int] existential List[T] forSome {type T} higher-kinded List

Upload: vasil-remeniuk

Post on 15-Jul-2015

111 views

Category:

Sports


0 download

TRANSCRIPT

Page 1: Types by Adform Research

Picking up from session 1

OOP/modular

• named BitSet

• compound Channel with Logged

• refined Channel {def close(): Unit }

Functional

• parametrized List[Int]

• existential List[T] forSome {type T}

• higher-kinded List

Page 2: Types by Adform Research

Picking up from session 1

• Self types

• Type members

• Implicits

• Type classes

• Logic programming with types

• Shapeless

Page 3: Types by Adform Research

Reminder

Page 4: Types by Adform Research

Self types

trait S3Connector { this: S3Processor =>

val accessKey = "fadsf76asf576dsa"

// ...

}

Limits where you can mix this trait in, i.e., it will only work like this:

class S3App extends S3Processor with S3Connector {

// ...

}

Page 5: Types by Adform Research

Type membersAlternative to type parameters, i.e.:

trait StringCollection extends Collection[String] {

// ...

}

vs

trait StringCollection extends Collection {

type T = String

// ...

}

Can also be

• abstract, so you could remove the String part as well

• type bounded, e.g., type T <: java.io.Closeable

Page 6: Types by Adform Research

Type members

Mostly useful for dealing with covariance and mixin problems:

class Animal {

def eat(f: Food)

}

class Cow extends Animal {

// cows only eat grass!

}

Page 7: Types by Adform Research

Type members

Mostly useful for dealing with covariance problems:

class Animal {

type SuitableFood

def eat(f: SuitableFood)

}

class Cow extends Animal {

type SuitableFood = Grass

}

Page 8: Types by Adform Research

Type membersCan be helpful in reducing redundancy for mixins:

trait IntTreeHelper { this: Tree[Int] =>

// ...

}

class TreeProcessor extends Tree[Int] with IntTreeHelper =>

// ...

}

vs

trait IntTreeHelper { this: Tree =>

type T = Int

// ...

}

class TreeProcessor extends Tree with IntTreeHelper =>

// ...

}

Page 9: Types by Adform Research

Implicits

Invisible entities within current scope:

• Parameters

• Methods

• Classes

Can be quite sneaky so don’t overdo it!

Page 10: Types by Adform Research

Implicit parameters

• Only one implicit keyword in signature

• Should come last

• Generally good for hiding configuration objects

implicit val arg1 = 1

implicit val arg2 = 2L

def ghostprint(a: Int)(implicit b: Int, c: Long) = println(a,b,c)

Page 11: Types by Adform Research

Implicit parameters

abstract class JobWithConf(args: Args) extends Job(args) {

implicit val configurationOfHadoop = …

}

class MyJob(args: Args) extends JobWithConf(args) {

val folderContents = getHDFSContents(folder)

}

object HDFSUtil{

def getHDFSContents(in: String)(implicit configuration: Configuration): List[String] =

Option(FileSystem.get(configuration).globStatus(new Path(in))) match {

case Some(a) => a.toList

case None => Nil

}.map(_.getPath.getName)

}

Page 12: Types by Adform Research

Implicit parameters

Helpful predefined function is implicitly[T], which ”catches” an implicit:

def implicitly[T](implicit e: T): T = e

Actually, configurationOfHadoop from the previous slide is defined as

@transient implicit val configurationOfHadoop = implicitly[Mode] match {

case Hdfs(_, configuration) => configuration

case _ => sys.error("Not running on Hadoop!")

}

Page 13: Types by Adform Research

Implicit methods

Usually used to silently convert between types

class MyInt(val i: Int) {

def inc = new MyInt(i+1)

}

implicit def int2MyInt(i: Int) = new MyInt(i)

5.inc

Page 14: Types by Adform Research

Implicit classes

Same idea, used to “pimp your classes”:

implicit class MyInt(val i: Int) {

def inc = new MyInt(i+1)

}

5.inc

Page 15: Types by Adform Research

Implicit classes

You can also pimp companion objects:

implicit class SuperList(companion: List.type) {

def fillInterspersed[A](n: Int)(a: A, b: A) = …

}

Page 16: Types by Adform Research

View and context bounds

These are shortcuts for providing implicit conversions and wrappers:

// view bound

def f[A <% B](a: A) = a.bMethod

is equal todef f[A](a: A)(implicit ev: A => B) = a.bMethod

// context bound

def g[A : B](a: A) = h(a)

is equal todef g[A](a: A)(implicit ev: B[A]) = h(a)

Page 17: Types by Adform Research

Type classes

• come from Haskell

• no relation to OOP classes

• a facility for ad-hoc polymorphism (compile-time variant of subtype p-m)

• in Scala they are basically traits + implicits (context bounds)

Page 18: Types by Adform Research

Type classes

trait Monoid[T] {

def zero: T

def append(a: T, b: T): T

}

implicit object IntIsMonoid extends Monoid[Int] {

def zero = 0

def append(a: Int, b: Int) = a + b

}

implicit object StringIsMonoid extends Monoid[String] {

def zero = ""

def append(a: String, b: String) = a concat b // try to avoid + for Strings

}

Page 19: Types by Adform Research

Type classes

def sum[T](xs: List[T])(implicit monoid: Monoid[T]) =

xs.foldLeft(monoid.zero)(monoid.append)

//context bounds

def sum[T : Monoid](xs: List[T]) = {

val monoid = implicitly[Monoid[T]]

xs.foldLeft(monoid.zero)(monoid.append)

}

Page 20: Types by Adform Research

Logic programming

• imperative - state = functional

• functional - DFS = logic

• Predicates/constraints instead of functions:

pow(2,3) = 8 ~ pow(2,3,8)

• Essentially an interface to a theorem prover

Page 21: Types by Adform Research

Prolog

• created in early 70s

• archetypical LP language

• Towers of Hanoi:

move(1, L, R, C) :-

write(['Move top disk from ', L , ' to ', R]),

nl.

move(N, L, R, C) :-

N > 1,

M is N - 1,

move(M, L, C, R),

move(1, L, R, C),

move(M, C, R, L).

move(3, L, R, C).

Page 22: Types by Adform Research

Logic programming

Scala implicit search engine is sort of a prover:

• facts = implicit vals

• rules = implicit defs

Page 23: Types by Adform Research

Towers of Hanoi

sealed trait Name

case object Left extends Name

case object Right extends Name

case object Center extends Name

trait Move[N <: Nat, L <: Name, R <: Name, C <: Name]

Page 24: Types by Adform Research

Towers of Hanoi

implicit def move0[L <: Name,

R <: Name,

C <: Name]: Move[_1, L, R, C] =

new Move[_1, L, R, C] {}

Page 25: Types by Adform Research

Towers of Hanoi

implicit def move1[N <: Nat,

M <: Nat,

L <: Name,

R <: Name,

C <: Name]

(implicit ev0 : LT[_1, N],

ev1 : Diff.Aux[N, _1, M],

ev2 : Move[M, L, C, R],

ev3 : Move[_1, L, R, C],

ev4 : Move[M, C, R, L]): Move[N, L, R, C] =

new Move[N, L, R, C] {}

Page 26: Types by Adform Research

Towers of Hanoi

implicitly[Move[_3, Left.type, Right.type, Center.type]]

Page 27: Types by Adform Research

Shapeless

• So what are these Nat, LT, Diff.Aux things?

• These are type-level numbers and arithmetical operations defined in a library called Shapeless:

sealed trait Nat

sealed trait _0 extends Nat

sealed trait Succ[N <: Nat] extends Nat

type _1 = Succ[_0]

type _2 = Succ[_1]

...

trait LT[A <: Nat, B <: Nat]

object LT {

def apply[A <: Nat, B <: Nat](implicit lt: A < B): LT[A, B] = lt

type <[A <: Nat, B <: Nat] = LT[A, B]

implicit def lt1[B <: Nat] = new <[_0, Succ[B]] {}

implicit def lt2[A <: Nat, B <: Nat](implicit lt : A < B) = new <[Succ[A], Succ[B]] {}

}

Page 28: Types by Adform Research

Shapeless

• HLists: like tuples, but with variable arity and collection functionality

• (also can be created from case classes)

• HMap: bidirectional map, e.g. HMap[BiMapIS](23 -> "foo", "bar" -> 13)

• Coproducts: Like Either, but with arbitrary number of choices

• Lens: compositional getters and setters for nested case classes

• collections with statically known sizes

• typesafe casting (wrapping in an Option)

Page 29: Types by Adform Research

References

• http://debasishg.blogspot.com/2010/02/scala-self-type-annotations-for.html

• http://stackoverflow.com/questions/1154571/scala-abstract-types-vs-generics

• http://like-a-boss.net/2013/03/29/polymorphism-and-typeclasses-in-scala.html

• http://lanyrd.com/2014/scalaio-fr/sdgcwm

• https://apocalisp.wordpress.com/2010/06/08/type-level-programming-in-scala

• https://github.com/milessabin/shapeless/wiki/Feature-overview%3a-shapeless-2.0.0