This document provides a dictionary of scala programming concepts including definitions of common jargon like ADT, typeclasses, extension methods, and call-by semantics. It defines ADT as algebraic data types, which were introduced in languages like Algol 60 and ML, and pattern matching which allows decomposing ADT values. Typeclasses are defined as rules for types like equality, with instances providing implementations. Extension methods and implicit conversions add methods to types via implicit parameters. Call-by-name and call-by-need semantics are discussed in relation to lazy evaluation.
5. ADT = { Abstract Data Types } (not SCALA)
CLU (1970, MIT)
"An abstract data type defines a class of abstract objects which is completely
characterized by the operations available on those objects. This means that an
abstract data type can be defined by defining the characterizing operations for
that type."
// 1974, ACM Sigplan, Congress of very hight-level languages.
From today-s point of view: Interface
cluster stack[t] is create push pop isEmpty
%rep struct {
arr: array[t]
idx: Int
}
create = proc() returns(cvt) ….
push = proc(x:t) signal(overflow)
trait Stack[T]
{
def push(x:T): Unit
…….
}
Barbara Leskov
6. ADT = { Algebraic Data Type }
HOPE (1970, Edinburg)
From today-s point of view: ADT ;)
data list alpha = nil
++ alpha :: list alpha
(A, B) == Pair[A,B]
(A+B) == emulated by sealed trait
(a:A,b:B)== case classes.
A | B ~~ partially emulated by traits
(will be implemented in dotty)
A & B ~~ partially emulated by A with B
(will be implemented in dotty)
A => B == Function[A,B]
Rod Burstall
David MacQueen
Some initial set of types: A, B, C, ….
Operations on types: Pair [A*B]
records (set of name-value-pairs)
discriminated unions (one of A or B)
functions: A=>B
// often (incorrectly): discr. union == ADT
Equality by value
7. ADT = { Algebraic Data Type }
data X = A ++ B
data A = ‘A#integer#integer
data B = ‘B#string
(a:A,b:B)== case classes [or objects].
sealed trait X
case class A(x:Int,y:Int) extends X
case class B(s:String) extends X
discriminated unions (one of A or B)
// often (incorrectly): discr. union == ADT
A+B
A+0
B+0
BOOL
BOOL
isA
isB
8. Pattern Matching
HOPE (1970, Edinburg)
data list alpha = nil
++ alpha::list alpha
sealed trait List[+A]
class Nil extends List[Nothing]
class Cons[A](head:A, tail:List[A]) extends List[A]
Rod Burstall
David MacQueen
dec length: list(alpha) -> int
— length nil <= 0
— length (a::l) <= length(l) + 1
def length[A](l: List[A]): Int =
l match {
case Nil => 0
case Cons(head,tail) => 1+length(tail)
}
9. Pattern Matching
SCALA
data list alpha = nil
++ alpha::list alpha
sealed trait List[+A]
class Nil extends List[Nothing]
class Cons[A](head:A, tail:List[A]) extends List[A]
dec length: list(alpha) -> int
— length nil <= 0
— length (a::l) <= length(l) + 1
def length[A](l: List[A]): Int =
l match {
case Nil => 0
case Cons(head,tail) => 1+length(tail)
}
10. Pattern Matching
SCALA
data list alpha = nil
++ alpha::list alpha
sealed trait List[+A]
class Nil extends List[Nothing]
class Cons[A](head:A, tail:List[A]) extends List[A]
dec length: list(alpha) -> int
— length nil <= 0
— length (a::l) <= length(l) + 1
def length[A](l: List[A]): Int =
l match {
case Nil => 0
case head :: tail => 1+length(tail)
}
11. Pattern Matching
Why Pattern Matching is better than sequence of IF-s ?
- Binding. (i.e. information from structure is extracted into variables)
We have not only algebraic, but object-oriented types.
- Views. (bridge, which represent object as algebraic type). Wadler, 1984
- Pattern objects. (Pattern-object method call return algebraic type)
- ODersky, 2006
- Exhaustive checking (if we miss something then we will see this)
12. x match {
case A(x,y) => y1
….
}
We have not only algebraic, but object-oriented types.
Pattern-Object
object A {
def unapply(x: X): Option[(A,B)]
}
extractor
Regular expressions:
final val StackElement =
“""W+([^)]+)(([^:]*):([^)]*))W*""".r
line match {
case StackElement(class,file,lineno) => ….
….
}
sealed trait Option[+A]
case class Some[A](a:A) extends Option[A]
case object None extends Option[Nothing]
13. val fac: Int => Int = {
case 0 => 1
case n => n*fac(n-1)
}
Partial functions syntax:
object Succ
{
def unapply(n: Int):Option[Int] =
if (n==0) None
else Some(n-1)
}
{ case (x,y) => (y,x) }
val positiveOne: Int => Int = {
case Succ(n) => 1
}
positiveOne.isDefinedAt(0)
false
positiveOne.isDefinedAt(3)
true
14. Partial functions:
val positiveOne: Int => Int = {
case Succ(n) => 1
}
positiveOne.isDefinedAt(0)
false
positiveOne.isDefinedAt(3)
true
PartialFunction[A,B]
B
Boolean
A
apply
isDefinedAt
16. Nominative typing (type == name)
{ def x:Int ; def y: Int } val a = A(1,2)
val b = new B(1,2)
f(a) ==> 3
f(b) ==> 3
Structured typing (type == structure)
case class A(x: Int, y: Int)
class B(x: Int, y: Int)
A != B
- Effective implementation in JVM
- Simula, Clu, C++, Java, …..
~ (A <: B)
~ (B <: A)
def f(p: { def x:Int ; def y: Int }):Int =
p.x + p.y
- implementation in JVM require reflection (can be better)
- ML, OCaml, Go
- theoretically have less corner cases than nominative
17. Refined type
Generics [Parametric Polymorphism]
B {
def z: Int
}
F[T]
- Structured type, based on nominative.
- Scala: structured types are refinement of AnyRef
Existential types: F[_] F[X] for Some X
Bounded type parameters:
Type aliases
F[T <: Closeable]
F[T <: { def close(): Unit }]
trait Expression[A]
{
type Value = A
}
trait Expression
{
type Value <: X
}
Undefined type alias
Scolem type
//CLU where
18. Traits:
trait Interpeter {
type Value
}
trait BaseInterpreter[A] extends Additive with Multiplicative with Show
{
type Value = A
}
Flavours (Flavours, [LISP dialects]) 1980, MIT
Mixing
trait Show {
this: Interpreter =>
def show
}
trait Additive {
this: Interpreter =>
def plus(x:Value, y:Value): Value
}
// Howard Cannon, David Moor
(CLOS, OCaml, Groovy, Python ..)
19. Traits:
trait LoggedInterpreter[A] extends BaseInterpreter[A]
with Logged with LoggedAdditive
trait LoggedAdditive extends Additive {
this => Logged
def plus(x:Value, y: Value) : Value =
{
log(s”(${x}+${y}”)
super.plus(x,y)
}
}
trait Additive {
this: Interpreter =>
def plus(x:Value, y:Value): Value
}
// AOP (aspect oriented programming)
// Flavours
: around
: before-next
: after-next
20. Type classes.
class Eq a where
== :: a -> a -> Bool
/= :: a -> a -> Bool
class (Eq a) => Ord a
where
compare :: a->a->Int
instance Ord Int where
compare x y = (x-y)
//addition to Haskell, Wadler, 1988
Constructor classes (type classes with multiple type parameters).
//addition to Haskell, Jone, 1993
instance (Eq a) (Eq b) => Eq(Pair a b) where
== (Pair x y) (Pair z w) =
x == z and y == w
classes = rules; instances = adaptors to this rules
22. implicit (val, def, classes )
- define rules of your world
- can be usable via implicit parameters
- implicit search <=> logical deduction
- can be dangerous.
implicit def stringToInt(s:String):Int = s.toInt
def f(x:Int):Int = x+1
f(“45”)
23. implicit (val, def, classes )
- define rules of your world
- can be usable via implicit parameters
- implicit search <=> logical deduction
- can be dangerous.
implicit def toJson(x:Int): Json = JsonNumeric(10)
def printAsJson[A](x:A)(implicit convert:A=>Json): String =
convert(x).prettyPrint
24. Type classes.
//Libraries: universal rules (like ontologies in philosophy)
scalaz : https://github.com/scalaz/scalaz
spire/algebra: https://github.com/non/algebra
(now - part of cats)
//Potenial problem: premature abstraction
// Human is an upright, featherless, ripped with broad, flat nails
+
Z / 10^64 Z << BigInt
Z{ |x| < 10^32} <<ERROR
25. Extension methods.
//implicit-based technique (pimp my library pattern [obsolete name])
implicit class WithPow(x: Int) {
def pow(y: Int): Int = Math.pow(x,y).toInt
}
scala> 2 pow 3
scala> res1: Int = 8
• pow — Int have no pow method
• => compiler search for implicit with pow
26. Scala types.
//whats-left for advanced talks:
42.type
Dynamic
// Homework:
Path dependency issues.
What’s left out of scala type system (?)
27. Call by ……….
Value.
Reference:
Name
Need
// value is copied.
// reference is copied by value.
// reference in language must exists
// Algol 68 (today - call by closure)
// lazy one-time evaluation
28. Call by ……….
Name // Algol 68 (today - call by closure)
def doWhile(x: => Boolean)(f : =>Unit)
{ while(x) { f } }
doWhile(x < 10)(x = x + 1)
29. Call by ……….
Need
def dupN[A](n: Int, v : =>A): Seq[A] =
{ lazy val neededV = v
for( i <- 1 to N) yield v
}
30. Scala.
Scala / Dotty : like grand unification theory
for large subset of type theories.
Mathematical jargon hide quite simple patterns.
Questions ?
// ruslan@shevchenko.kiev.ua