Download - Types by Adform Research, Saulius Valatka
A bit of history
Type theory – invented by Russel in 1903 to prevent Russel’s paradox
Idea: limit the expressive power and disallow inconsistencies
In a nutshell
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[_]
Declaring types
scala> val y: Int = 1 // explicit type declaration
y: Int = 1
scala> val x = 1 // type inference
x: Int = 1
scala> def double(i: Int): Int = i * 2
double: (i: Int)Int // type of method
// (technically not the same as a function)
Defining new named types
scala> class Animal
scala> class Dog extends Animal
scala> class Cat extends Animal
scala> val lassie: Dog = new Dog
scala> val garfield: Cat = new Cat
scala> val garfieldAnimal: Animal = garfield
Algebraic Types
• These are “data-only” types, i.e. case classes
• Pattern match to deconstruct them
scala> case class Person(name: String, id: Int)
defined class Person
There is only one value of Null
scala> val n: Null = null
n: Null = null
scala> val n: Null = garfield
<console>:10: error: type mismatch;
found : Cat
required: Null
val n: Null = garfield
^
There are no values of Nothing !
scala> val nothing: Nothing = throw new Exception("die")
java.lang.Exception: die
... 33 elided
Traits
scala> trait Cosmic {
def flyToSpace: Unit
def flyTwice: Unit = { flyToSpace; flyToSpace } // Can contain implementations!
}
defined trait Cosmic
scala> class SpaceDog extends Dog with Cosmic {
def flyToSpace = println("flying!")
}
defined class SpaceDog
Trait linearization
class Animal
trait Furry extends Animal
trait HasLegs extends Animal
trait FourLegged extends HasLegs
class Cat extends Animal with Furry with FourLegged
reverse –> expand –> right-keep-unique -> add-common
Type refinement
scala> val laika = new Dog with Cosmic { // type refinement !
def flyToSpace = println("done!")
}
scala> laika.flyToSpace
done!
Types ≠ Classes
Key idea: A type is a broader concept than a class !
Type declarations are NOT ONLY class declarations!
scala> def eatInSpace(a: Edible with Cosmic) = println("om nom nom!")
eatInSpace: (a: Edible with Cosmic)Unit
Anonymous and Structural types
scala> val xz = new { def act = println("acting!") }
xz: AnyRef{def act: Unit} = $anon$1@74224c87
scala> def act(a: { def act: Unit }) = a.act
act: (a: AnyRef{def act: Unit})Unit
scala> act(xz)
acting!
Type Parameters
scala> class MyList[T]
defined class MyList
scala> val x = new MyList[Int]
scala> val y = new MyList[String]
Tuples and Unit
scala> val x: Tuple2[Int, String] = (1, "abc")
x: (Int, String) = (1,abc)
scala> val x: (Int, String) = (1, "abc") // syntactic sugar
x: (Int, String) = (1,abc)
scala> val u: Unit = () // Like a tuple with 0 arguments !
u: Unit = ()
Types of functions
scala> val doubler: Function[Int, Int] = x => x * 2
doubler: Function[Int,Int] = <function1>
scala> val doubler: Int => Int = x => x * 2 // Alternative syntax
doubler: Int => Int = <function1>
Syntactic Sugar
scala> class @@[A, B]
scala> val test = new (Int @@ String)
test: @@[Int,String] = $at$at@6bddea9
scala> trait MyIntFn extends (Int => Int)
Variance
• Is List[Dog] a subtype of List[Animal] ? You decide!
class Covariant[+T]
class Contravariant[-T]
class Invariant[T]
Variance
List[+T] // List[Dog] is a List[Animal]
Comparator[-B] // Comparator[Animal] can work as Comparator[Dog]
Function[-A, +R] // Think about it!
mutable.Set[A] // Can you say why ?
Covariant types can only appear in return positions
Contravariant types can only appear in argument positions
e.g. def apply(arg: A): R
Type Bounds
class CosmicList[A <: Cosmic]
class CosmicAnimalList[A <: Animal with Cosmic]
class ClosableList[A <: { def close: Unit }]
class ComparatorList[T >: Comparable]
Existential Types
scala> def length[T](list: List[T]): Int = list.length
length: [T](list: List[T])Int
scala> def length(list: List[T] forSome { type T }): Int = list.length
length: (list: List[_])Int
scala> def length(list: List[_]): Int = list.length // equivalent
length: (list: List[_])Int
Existential types
Array[T] forSome { type T } // Array[_]
Array[T forSome { type T }] // Array[Any]
Map[Class[T forSome { type T }], String]
Map[Class[T] forSome { type T }, String] // Map[Class[_], String]
Map[Class[T], String] forSome { type T }
Type constructors
• List is a type constructor, i.e. given a type, it produces a type
• List is not a type! List[Int] is a type!
Higher Kinded Types
scala> class ContainerFactory[T, C[_]]
defined class ContainerFactory
scala> class ListFactory[T] extends ContainerFactory[T, List]
defined class ListFactory
Kinds of types
Int has kind * // analogous to value 1
List[Int] has kind * // analogous to value “abc”
List[_] has kind * // analogous to value ‘a’
List has kind * -> * // analogous to function x => x * x
ContainerFactory has kind (*, * -> *) -> * // analogous to (x, f) => f(x)
1000000$ question
• What is a type equivalent to plus(2, _) ? i.e. x => plus(2, x)
• E.g. given Either[A, B] get a type constructor that produces types Either[Int, T] given a type T
Naïve answer
• Either[Int, _] ?
scala> class EitherFactory[T] extends ContainerFactory[T, Either[Int, _]]
<console>:8: error: Either[Int, _] takes no type parameters, expected: one
class EitherFactory[T] extends ContainerFactory[T, Either[Int, _]]
Answer
class EitherFactory[T] extends ContainerFactory[T, ({ type λ[α] = Either[Int, α]})#λ]
defined class EitherFactory
Type lambdas !!
Future syntax: [α]=Either[Int, α]
Type members will be discussed next time
References
• http://stackoverflow.com/a/3113741/919707 a list of scala types
• Wample & Payne, “Programming Scala”, chapter 12
• http://www.infoq.com/presentations/data-types-issues
• https://github.com/lampepfl/dotty EPFL’s attempt to optimize the system