functional scala ii (in practice)

112
Mario Gleichmann JUG Frankfurt / Main Functional Scaλa … in Practice 20.10.2010 Java User Group Frankfurt / Main Mario Gleichmann

Upload: mario-gleichmann

Post on 07-May-2015

2.780 views

Category:

Technology


2 download

TRANSCRIPT

Page 1: Functional Scala II (in practice)

Mario Gleichmann JUG Frankfurt / Main

Functional Scaλa

… in Practice

20.10.2010

Java User Group Frankfurt / MainMario Gleichmann

Page 2: Functional Scala II (in practice)

Mario Gleichmann JUG Frankfurt / Main2

Introduction

Mario Gleichmann

site: www.mg-informatik.de

blog: 'brain driven development'

gleichmann.wordpress.com

mail: [email protected]

Page 3: Functional Scala II (in practice)

Mario Gleichmann JUG Frankfurt / Main3

Summary

Page 4: Functional Scala II (in practice)

Mario Gleichmann JUG Frankfurt / Main4

What is Functional Programming ?

Functional Style

val sum = fold( 1 to 10, add )

Expression based

Computation method is function application

fcn

Page 5: Functional Scala II (in practice)

Mario Gleichmann JUG Frankfurt / Main5

What makes a Function ?

val add = ( x :Int, y :Int ) => x + y

Function Types

Type of add : ( Int , Int ) => Int

Obj

Page 6: Functional Scala II (in practice)

Mario Gleichmann JUG Frankfurt / Main6

Closures

var limit = 18 val isAdult = ( age :Int ) => age >= limit

'Closed term'

appl

'closing over'

Page 7: Functional Scala II (in practice)

Mario Gleichmann JUG Frankfurt / Main7

Algebraic Datatypes

data Tree = Empty | Leaf Int | Node Int Tree Tree

abstract case class Tree() case object Empty extends Tree case class Leaf( value: Int ) extends Tree

case class Node( value: Int, left :Tree, right: Tree ) extends Tree

Example - Tree

insrt

Page 8: Functional Scala II (in practice)

Mario Gleichmann JUG Frankfurt / Main8

Pattern Matching

val depth :Tree => Int = _ match { case Empty => 0 case Leaf( _ ) => 1 case Node( _, left, right ) => 1 + max( depth( left ), depth( right ) )}

Prt isb

Page 9: Functional Scala II (in practice)

Mario Gleichmann JUG Frankfurt / Main9

Partial Functions

type =>?[-A, +B] = PartialFunction[A, B]

val publisherRegionDE : Isbn =>? String = { case Isbn( 3, pubNr, _ ) => "D" + ( pubNr.toString charAt 0 )}

publisherRegionDE.isDefinedAt( Isbn( 0, 677873, 8823 ) ) )

>> false

chn

Page 10: Functional Scala II (in practice)

Mario Gleichmann JUG Frankfurt / Main10

Comprehensions

val factors = ( n :Int ) => for( x <- ( 1 to n ) if n % x == 0 ) yield x ...

val prime = ( n :Int ) => factors( n ).toList == List( 1, n )

val primes = (n :Int) => for( x <- (1 to n) if prime( x ) ) yield x

Hgh rdr Fcn

Page 11: Functional Scala II (in practice)

Mario Gleichmann JUG Frankfurt / Main11

Higher Order Functions

val filter = ( predicate: Int => Boolean , xs :List[Int] ) => {

for( x <- xs; if predicate( x ) ) yield x }

Fcn Tp

Page 12: Functional Scala II (in practice)

Mario Gleichmann JUG Frankfurt / Main12

Lambda Expressions

filter( num => num % 2 == 0, List( 1, 2, 3, 4, 5, 6 ) )

filter( _ > 0, List( -1, 5, 0, -3, 7 ) )

fst arg

Page 13: Functional Scala II (in practice)

Mario Gleichmann JUG Frankfurt / Main13

Partial Application

Page 14: Functional Scala II (in practice)

Mario Gleichmann JUG Frankfurt / Main14

Partial Application

val isPrime = (x :Int) => ( 2 to x/2 ).forall( x % _ != 0 )

Type of isPrime: Int => Boolean

def prms wthn

Page 15: Functional Scala II (in practice)

Mario Gleichmann JUG Frankfurt / Main15

Partial Application

val isPrime = (x :Int) => ( 2 to x/2 ).forall( x % _ != 0 )

val primesWithin = ( xs :List[Int] ) => filter( isPrime , xs )

Delegation

Type of filter: ( Int => Boolean, List[Int] ) => List[Int]

fxd var

Page 16: Functional Scala II (in practice)

Mario Gleichmann JUG Frankfurt / Main16

Partial Application

val isPrime = (x :Int) => ( 2 to x/2 ).forall( x % _ != 0 )

val primesWithin = ( xs :List[Int] ) => filter( isPrime , xs )

Delegation

variablefixed

appl nappl

Page 17: Functional Scala II (in practice)

Mario Gleichmann JUG Frankfurt / Main17

Partial Application

val isPrime = (x :Int) => ( 2 to x/2 ).forall( x % _ != 0 )

val primesWithin = filter( isPrime, _ :List[Int] )

New from Old ...

unappliedapplied

Fcn Tp

Page 18: Functional Scala II (in practice)

Mario Gleichmann JUG Frankfurt / Main18

Partial Application

val isPrime = (x :Int) => ( 2 to x/2 ).forall( x % _ != 0 )

val primesWithin = filter( isPrime, _ :List[Int] )

New from Old ...

Type of primesWithin: List[Int] => List[Int]

Crrng

Page 19: Functional Scala II (in practice)

Mario Gleichmann JUG Frankfurt / Main19

Currying

Page 20: Functional Scala II (in practice)

Mario Gleichmann JUG Frankfurt / Main20

Currying

val filter = ( pred: Int => Boolean , xs :List[Int] ) => {

for( x <- xs; if pred( x ) ) yield x }

Type of filter: ( Int => Boolean , List[Int] ) => List[Int]

Crrd fcn

Page 21: Functional Scala II (in practice)

Mario Gleichmann JUG Frankfurt / Main21

Currying

'Higher Order Lambda Closures' ...

val filter = ( pred: Int => Boolean ) => ( xs :List[Int] ) => {

for( x <- xs; if pred( x ) ) yield x }

Crrd fcn Tp

Page 22: Functional Scala II (in practice)

Mario Gleichmann JUG Frankfurt / Main22

Currying

'Higher Order Lambda Closures' ...

Type of filter: ( Int => Boolean ) => ( List[Int] ) => List[Int]

sngl arg

val filter = ( pred: Int => Boolean ) => ( xs :List[Int] ) => {

for( x <- xs; if pred( x ) ) yield x }

Page 23: Functional Scala II (in practice)

Mario Gleichmann JUG Frankfurt / Main23

Currying

Curried FunctionCurried Function

'Higher Order Lambda Closures' ...

xpln

Type of filter: ( Int => Boolean ) => ( List[Int] ) => List[Int]

sngl arg

val filter = ( pred: Int => Boolean ) => ( xs :List[Int] ) => {

for( x <- xs; if pred( x ) ) yield x }

Page 24: Functional Scala II (in practice)

Mario Gleichmann JUG Frankfurt / Main24

Currying

'Higher Order Lambda Closures' ...

A function ... accepting one (Function) Arg

... resulting in another function

lmbd xpr

val filter = ( pred: Int => Boolean ) => ( xs :List[Int] ) => {

for( x <- xs; if pred( x ) ) yield x }

Type of filter: ( Int => Boolean ) => ( List[Int] ) => List[Int]

Page 25: Functional Scala II (in practice)

Mario Gleichmann JUG Frankfurt / Main25

Currying

'Higher Order Lambda Closures' ...

val filter = ( pred: Int => Boolean ) => ( xs :List[Int] ) => {

for( x <- xs; if pred( x ) ) yield x }

Type of filter: ( Int => Boolean ) => List[Int] => List[Int]

... is defined as a Lambda expession

cls ovr

Page 26: Functional Scala II (in practice)

Mario Gleichmann JUG Frankfurt / Main26

Currying

'Higher Order Lambda Closures' ...

val filter = ( pred: Int => Boolean ) => ( xs :List[Int] ) => {

for( x <- xs; if pred( x ) ) yield x }

Type of filter: ( Int => Boolean ) => List[Int] => List[Int]

... closes over to Arguments (Scope) of surrounding Function 'filter'

Smp prms wthn

Page 27: Functional Scala II (in practice)

Mario Gleichmann JUG Frankfurt / Main27

Example 1 – Extract primes

val filter = ( pred: Int => Boolean ) => ( xs :List[Int] ) => {

for( x <- xs; if pred( x ) ) yield x }

val primesWithin = filter( isPrime )

Fcn Tp

Page 28: Functional Scala II (in practice)

Mario Gleichmann JUG Frankfurt / Main28

Example 1 – Extract primes

val filter = ( pred: Int => Boolean ) => ( xs :List[Int] ) => {

for( x <- xs; if pred( x ) ) yield x }

val primesWithin = filter( isPrime )

Type of primesWithin: List[Int] => List[Int]

appl

Page 29: Functional Scala II (in practice)

Mario Gleichmann JUG Frankfurt / Main29

Example 1 – Extract primes

val filter = ( pred: Int => Boolean ) => ( xs :List[Int] ) => {

for( x <- xs; if pred( x ) ) yield x }

val primesWithin = filter( isPrime )

...primesWithin( List( 3, 4, 5, 6, 7 ) ) >> List( 3, 5, 7 )

Smp rc mgmt

Page 30: Functional Scala II (in practice)

Mario Gleichmann JUG Frankfurt / Main30

Example 2 – Ressource Management

val initQuery = (dataSource :DataSource) => (query :String) => ( extractor :ResultSet => Unit ) => { try{ val conn = dataSource.getConnection val stmt = conn.createStatement val resultSet = stmt.executeQuery( query ) extractor( resultSet ) } finally{ try{ if( conn != null ) conn.close } finally{ if( stmt != null ) stmt.close } } }

appl

Page 31: Functional Scala II (in practice)

Mario Gleichmann JUG Frankfurt / Main31

Example 2 – Ressource Management

val dataSource :DataSource = ...;

...val query = initQuery( dataSource )

query( "select * from User where age > 18" ) { result :ResultSet =>

while( result.next ) { .... } }

query( "select * from Account where balance < 1000" ) { result :ResultSet =>

while( result.next ) { .... } }

smmy

Page 32: Functional Scala II (in practice)

Mario Gleichmann JUG Frankfurt / Main32

Combinators

Page 33: Functional Scala II (in practice)

Mario Gleichmann JUG Frankfurt / Main33

Combinators

val power : Int => Int => Int =

( base :Int ) => ( exp :Int ) =>

if( exp == 1 ) base else base * power( base )( exp - 1 )

...

val square = power( _ :Int )( 2 )

Page 34: Functional Scala II (in practice)

Mario Gleichmann JUG Frankfurt / Main34

Combinators

val power : Int => Int => Int =

( base :Int ) => ( exp :Int ) =>

if( exp == 1 ) base else base * power( base )( exp - 1 )

...

val square = power( _ :Int )( 2 )

Type of square : Int => Int

Page 35: Functional Scala II (in practice)

Mario Gleichmann JUG Frankfurt / Main35

Combinators

val power : Int => Int => Int =

( base :Int ) => ( exp :Int ) =>

if( exp == 1 ) base else base * power( base )( exp - 1 )

...

val square = power( _ :Int )( 2 )

Partial Application 'in the middle'

Page 36: Functional Scala II (in practice)

Mario Gleichmann JUG Frankfurt / Main36

Combinators

def flipArgs [A, B, C] ( f: A => B => C ) : B => A => C = ( x: B ) => ( y: A ) => f (y) (x)

Transforms to another Function, expecting arguments in reversed order

Transforms to another Function, expecting arguments in reversed order

Page 37: Functional Scala II (in practice)

Mario Gleichmann JUG Frankfurt / Main37

Combinators

def flipArgs [A, B, C] ( f: A => B => C ) : B => A => C = ( x: B ) => ( y: A ) => f (y) (x)

val square = flipArgs( power )( 2 )

… now just exploit Currying

Page 38: Functional Scala II (in practice)

Mario Gleichmann JUG Frankfurt / Main38

Combinators

Function Composition

f :: B => C

g :: A => B

x ∈ A

( f o g )( x ) = f ( g ( x ) )

( f o g ) :: A => C

Page 39: Functional Scala II (in practice)

Mario Gleichmann JUG Frankfurt / Main39

Combinators : Function Composition

def o [A,B,C] ( f: B => C ) ( g: A => B ) : A => C =

( x :A ) => f( g( x ) )

...val mult = ( x :Int ) => ( y: Int ) => x * y

val add = ( x :Int ) => ( y: Int ) => x + y

...val doubleSucc = o ( mult(2) ) ( add(1) ) Type of doubleSucc : Int => Int

Page 40: Functional Scala II (in practice)

Mario Gleichmann JUG Frankfurt / Main40

Combinators : Function Composition

def o [A,B,C] ( f: B => C ) ( g: A => B ) : A => C =

( x :A ) => f( g( x ) )

...val mult = ( x :Int ) => ( y: Int ) => x * y

val add = ( x :Int ) => ( y: Int ) => x + y

...val doubleSucc = o ( mult(2) ) ( add(1) ) doubleSucc( 7 )

>> 16

Page 41: Functional Scala II (in practice)

Mario Gleichmann JUG Frankfurt / Main41

Combinators : Function Composition

def o [A,B,C] ( f: B => C ) ( g: A => B ) : A => C =

( x :A ) => f( g( x ) )

...val mult = ( x :Int ) => ( y: Int ) => x * y

val add = ( x :Int ) => ( y: Int ) => x + y

...val doubleSucc = o ( mult(2) ) ( add(1) ) doubleSucc( 7 )

>> 16Postfix ...

Page 42: Functional Scala II (in practice)

Mario Gleichmann JUG Frankfurt / Main42

Combinators : Function Composition

class RichFunc [B, C] ( f: B => C ) {

def o[A] ( g: A => B ) = (x :A) => f( g( x ) )}

implicit def toRichFunc[B,C]( f: B => C ) = new RichFunc( f )

...val doubleSucc = mult(2) o add(1) doubleSucc( 7 )

>> 16

Infix !!!

Page 43: Functional Scala II (in practice)

Mario Gleichmann JUG Frankfurt / Main43

Combinators : Function Composition

class RichFunc [B, C] ( f: B => C ) {

def o[A] ( g: A => B ) = (x :A) => f( g( x ) )}

implicit def toRichFunc[B,C]( f: B => C ) = new RichFunc( f )

...val doubleSucc = mult(2) o add(1) doubleSucc( 7 )

>> 16

'Point free style' of function definition

Page 44: Functional Scala II (in practice)

Mario Gleichmann JUG Frankfurt / Main44

Example: Word Counter

Count all even words within a sentence:

“Hello World“ → 0

“The fox jumps over the lazy dog“ → 2

"This sentence contains five even words" → 5

Page 45: Functional Scala II (in practice)

Mario Gleichmann JUG Frankfurt / Main45

Example: Word Counter

Count all even words within a sentence:

“Hello World“ → 0

“The fox jumps over the lazy dog“ → 2

"This sentence contains five even words" → 5

Basic Functions:

parse Words → Word to length → filter even → count

Page 46: Functional Scala II (in practice)

Mario Gleichmann JUG Frankfurt / Main46

Example: Word Counter

val words = ( sentence : String ) => sentence.split( " " ).toList val length = ( ws :List[String] ) => for( w <- ws ) yield w.length

val filter = ( predicate: Int => Boolean ) => ( xs :List[Int] ) => ...

val even = ( i :Int ) => i % 2 == 0

val size = ( xs :List[ _ ] ) => xs.size

Basic Functions

Page 47: Functional Scala II (in practice)

Mario Gleichmann JUG Frankfurt / Main47

Example: Word Counter

val words = ( sentence : String ) => sentence.split( " " ).toList val length = ( ws :List[String] ) => for( w <- ws ) yield w.length

val filter = ( predicate: Int => Boolean ) => ( xs :List[Int] ) => ...

val even = ( i :Int ) => i % 2 == 0

val size = ( xs :List[ _ ] ) => xs.size

val evenWordCount = size o filter( even ) o length o words

Type of evenWordCount : String => Int

Page 48: Functional Scala II (in practice)

Mario Gleichmann JUG Frankfurt / Main48

Example: Word Counter

val words = ( sentence : String ) => sentence.split( " " ).toList val length = ( ws :List[String] ) => for( w <- ws ) yield w.length

val filter = ( predicate: Int => Boolean ) => ( xs :List[Int] ) => ...

val even = ( i :Int ) => i % 2 == 0

val size = ( xs :List[ _ ] ) => xs.size

val evenWordCount = size o filter( even ) o length o words

val evenWordCount = (sentence :String ) =>

size ( filter( even ) ( length( words( sentence ) ) ) )

vs.

Page 49: Functional Scala II (in practice)

Mario Gleichmann JUG Frankfurt / Main49

Example: Word Counter

val words = ( sentence : String ) => sentence.split( " " ).toList val length = ( ws :List[String] ) => for( w <- ws ) yield w.length

val filter = ( predicate: Int => Boolean ) => ( xs :List[Int] ) => ...

val even = ( i :Int ) => i % 2 == 0

val size = ( xs :List[ _ ] ) => xs.size

val evenWordCount = size o filter( even ) o length o words

evenWordCount( "this sentence contains five even words" )

>> 5

Page 50: Functional Scala II (in practice)

Mario Gleichmann JUG Frankfurt / Main50

Fundamental Functions

Page 51: Functional Scala II (in practice)

Mario Gleichmann JUG Frankfurt / Main51

Fundamental Functions

def sum ( list : List[Int] ) : Int = list match { case Nil => 0 case x :: xs => x + sum( xs )}

Page 52: Functional Scala II (in practice)

Mario Gleichmann JUG Frankfurt / Main52

Fundamental Functions

def product ( list : List[Int] ) : Int = list match { case Nil => 1 case x :: xs => x * product( xs )}

Page 53: Functional Scala II (in practice)

Mario Gleichmann JUG Frankfurt / Main53

Fundamental Functions

def allTrue ( ys : List[Boolean] ) : Boolean = ys match { case Nil => true case x :: xs => x and allTrue( xs ) }

Page 54: Functional Scala II (in practice)

Mario Gleichmann JUG Frankfurt / Main54

Fundamental Functions : reduce

def reduce ( list : List[ T ] ) : R = list match { case Nil => ? case x :: xs => x ʘ reduce( xs ) }

Page 55: Functional Scala II (in practice)

Mario Gleichmann JUG Frankfurt / Main55

Fundamental Functions : reduce

def reduce ( list : List[ T ] ) : R = list match { case Nil => ? case x :: xs => x ʘ reduce( xs ) }

'unit'

'subsuming operation'

Page 56: Functional Scala II (in practice)

Mario Gleichmann JUG Frankfurt / Main56

Fundamental Functions : reduce

def reduce[T,R] ( fun : T => R => R ) ( unit : R ) ( list : List[T] ) : R = list match { case Nil => unit case x :: xs => fun ( x ) ( reduce( fun )( unit )( xs ) ) }

Page 57: Functional Scala II (in practice)

Mario Gleichmann JUG Frankfurt / Main57

Fundamental Functions : reduce

def reduce[T,R] ( fun : T => R => R ) ( unit : R ) ( list : List[T] ) : R = list match { case Nil => unit case x :: xs => fun ( x ) ( reduce( fun )( unit )( xs ) ) }

reduce ʘ unit t1 :: t2 :: t3 :: t4 :: Nil => t1 ʘ ( t2 ʘ ( t3 ʘ ( t4 ʘ unit ) ) )

Page 58: Functional Scala II (in practice)

Mario Gleichmann JUG Frankfurt / Main58

Fundamental Functions : reduce

val add = (x : Int) => (y : Int) => x + y val mult = (x : Int) => (y : Int) => x * y ... val sum = reduce ( add ) ( 0 ) _ val product = reduce ( mult ) ( 1 ) _

... sum( List( 1, 2, 3, 4 ) )

product( List( 1, 2, 3, 4 ) )

>> 10

>> 24

Page 59: Functional Scala II (in practice)

Mario Gleichmann JUG Frankfurt / Main59

Fundamental Functions : reduce

val or = ( x :Boolean ) => ( y :Boolean ) => x || y

val and = ( x :Boolean ) => ( y :Boolean ) => x && y

val not = ( x :Boolean ) => !x ... val existOneTrue = reduce ( or ) ( false ) _

val allFalse = not o reduce ( or ) ( false ) _

val allTrue = reduce ( and ) ( true ) _

... allTrue( List( 1 < 2, 3 == 3, 1 + 1 == 2 ) ) >> true

Page 60: Functional Scala II (in practice)

Mario Gleichmann JUG Frankfurt / Main60

Example: List concatenation

def append[T] (x:T) (xs:List[ _ ]) = x :: xs val listConcat = reduce ( append ) _

listConcat ( List( 1, 2, 3, 4 ) ) ( List( 8, 9 ) ) )>> List( 8, 9, 1, 2, 3, 4 ) listConcat ( List( true, true, false ) ) ( List( true, false ) ) )>> List( true, false, true, true, false )

Page 61: Functional Scala II (in practice)

Mario Gleichmann JUG Frankfurt / Main61

Example: List concatenation

def append[T] (x:T) (xs:List[ _ ]) = x :: xs val listConcat = reduce ( append ) _

listConcat ( List( 1, 2, 3, 4 ) ) ( List( 8, 9 ) ) )>> List( 8, 9, 1, 2, 3, 4 ) listConcat ( List( true, true, false ) ) ( List( true, false ) ) )>> List( true, false, true, true, false )

'unit''unit'

Page 62: Functional Scala II (in practice)

Mario Gleichmann JUG Frankfurt / Main62

Example: List concatenation

def append[T] (x:T) (xs:List[ _ ]) = x :: xs val listConcat = flipArgs( reduce ( append ) _ )

listConcat ( List( 1, 2, 3, 4 ) ) ( List( 8, 9 ) ) )>> List( 1, 2, 3, 4, 8, 9 ) listConcat ( List( true, true, false ) ) ( List( true, false ) ) )>> List( true, true, false, true, false )

Page 63: Functional Scala II (in practice)

Mario Gleichmann JUG Frankfurt / Main63

Example: List concatenation

def append[T] (x:T) (xs:List[ _ ]) = x :: xs val listConcat = flipArgs( reduce ( append ) _ )

listConcat ( List( 1, 2, 3, 4 ) ) ( List( 8, 9 ) ) )>> List( 1, 2, 3, 4, 8, 9 ) listConcat ( List( true, true, false ) ) ( List( true, false ) ) )>> List( true, true, false, true, false )

'unit''unit'

Page 64: Functional Scala II (in practice)

Mario Gleichmann JUG Frankfurt / Main64

Example: List concatenation

def append[T] (x:T) (xs:List[ _ ]) = x :: xs val listConcat = flipArgs( reduce ( append ) _ )

listConcat ( List( 1, 2, 3, 4 ) ) ( List( 8, 9 ) ) )

Type of result: List[Any]

!

Page 65: Functional Scala II (in practice)

Mario Gleichmann JUG Frankfurt / Main65

Example: List concatenation

def append[T] (x:T) (xs:List[ T ]) = x :: xs def listConcat[A] ( a: List[A]) ( b: List[A] ) : List[A] = reduce[ A, List[A] ] ( ( append[A] ) _ ) (b) (a)

listConcat ( List( 1, 2, 3, 4 ) ) ( List( 8, 9 ) ) )

Type of result: List[Int]

Page 66: Functional Scala II (in practice)

Mario Gleichmann JUG Frankfurt / Main66

More

Fundamental Functions

Page 67: Functional Scala II (in practice)

Mario Gleichmann JUG Frankfurt / Main67

Fundamental Functions

val doubleAll : List[Int] => List[Int] = _ match {

case Nil => Nil

case y :: ys => y * 2 :: doubleAll( ys )}

doubleAll( List( 1, 2, 3, 4 ) )

>> List( 2, 4, 6, 8 )

Page 68: Functional Scala II (in practice)

Mario Gleichmann JUG Frankfurt / Main68

Fundamental Functions

val toLength : List[String] => List[Int] = _ match { case Nil => Nil case y :: ys => y.length :: toLength( ys )}

toLength( List( "a", "ab", "abc", "abcde" ) ) )

>> List( 1, 2, 3, 5 )

Page 69: Functional Scala II (in practice)

Mario Gleichmann JUG Frankfurt / Main69

Fundamental Functions : map

val map : List[T] => List[R] = _ match { case Nil => Nil case y :: ys => f?( y ) :: map( ys )}

Page 70: Functional Scala II (in practice)

Mario Gleichmann JUG Frankfurt / Main70

Fundamental Functions : map

def map[T, R] ( f: T => R ) : List[T] => List[R] = ( xs : List[T] ) => xs match { case Nil => Nil case y :: ys => f( y ) :: map( f )( ys ) }

Page 71: Functional Scala II (in practice)

Mario Gleichmann JUG Frankfurt / Main71

Fundamental Functions : map

def map[T, R] ( f: T => R ) : List[T] => List[R] = ( xs : List[T] ) => xs match { case Nil => Nil case y :: ys => f( y ) :: map( f )( ys ) }

Accepting a function to apply on every element

Resulting in another function,accepting the List of elements

Page 72: Functional Scala II (in practice)

Mario Gleichmann JUG Frankfurt / Main72

Fundamental Functions : map

def map[T, R] ( f: T => R ) : List[T] => List[R] = ...

...val mult = (x : Int) => (y : Int) => x * y

val doubleAll = map( mult( 2 ) )

...val toLength = map( ( s :String ) => s.length )

Page 73: Functional Scala II (in practice)

Mario Gleichmann JUG Frankfurt / Main73

Fundamental Functions : map

val add = (x : Int) => (y : Int) => x + y

val sum = reduce ( add ) ( 0 ) _ val sumMatrix = sum o map( sum )

Type of sum : List[Int] => Int

Type of map( sum ) : List[List[Int]] => List[Int]

Type of sumMatrix : List[List[Int]] => Int

Page 74: Functional Scala II (in practice)

Mario Gleichmann JUG Frankfurt / Main74

Fundamental Functions : map

val add = (x : Int) => (y : Int) => x + y

val sum = reduce ( add ) ( 0 ) _ val sumMatrix = sum o map( sum )

...val matrix = List( List( 1, 2, 3 ), List( 4, 5, 6 ), List( 7, 8, 9 ) )

sumMatrix( matrix ) >> 45

Page 75: Functional Scala II (in practice)

Mario Gleichmann JUG Frankfurt / Main75

map via reduce

def applyAndPrepend [A, B] ( f: A => B ) =

( a :A ) => ( bs :List[B] ) => f( a ) :: bs

def map [A, B] ( f: A => B ) : List[A] => List[B] =

reduce ( applyAndPrepend( f ) ) ( Nil ) _

Page 76: Functional Scala II (in practice)

Mario Gleichmann JUG Frankfurt / Main76

map via reduce

def applyAndPrepend [A, B] ( f: A => B ) =

( a :A ) => ( bs :List[B] ) => f( a ) :: bs

def map [A, B] ( f: A => B ) : List[A] => List[B] =

reduce ( applyAndPrepend( f ) ) ( Nil ) _

X1 :: X2 :: X3 :: X4 :: Nil

f :: f :: f :: f :: Nil

Page 77: Functional Scala II (in practice)

Mario Gleichmann JUG Frankfurt / Main77

filter via reduce

def filter[T]( pred :T => Boolean ) : List[T] => List[T] = reduce ( ( x :T ) => ( acc :List[T] ) =>

if( pred( x ) ) x :: acc else acc ) ( Nil )

Page 78: Functional Scala II (in practice)

Mario Gleichmann JUG Frankfurt / Main78

Type Classes

Page 79: Functional Scala II (in practice)

Mario Gleichmann JUG Frankfurt / Main79

Type Classes

def sum( xs : List[Int] ) : Int = xs match { case Nil => 0 case head :: tail => head + sum( tail )}

Page 80: Functional Scala II (in practice)

Mario Gleichmann JUG Frankfurt / Main80

Type Classes

def sum( xs : List[String] ) : String = xs match { case Nil => ““ case head :: tail => head + sum( tail )} Concatenation !

Page 81: Functional Scala II (in practice)

Mario Gleichmann JUG Frankfurt / Main81

Type Classes

def sum[A]( xs : List[A] ) : A = xs match { case Nil => ? case head :: tail => head ? sum( tail )}

Page 82: Functional Scala II (in practice)

Mario Gleichmann JUG Frankfurt / Main82

Type Classes

def sum[A]( xs : List[A] ) : A = xs match { case Nil => ? case head :: tail => head ? sum( tail )}

'neutral' element

element composition

Page 83: Functional Scala II (in practice)

Mario Gleichmann JUG Frankfurt / Main83

Type Classes

trait SemiGroup[S] { def add( x : S, y : S ) : S}

trait Monoid[M] extends SemiGroup[M] { def unit : M}

'neutral' element

element composition

Page 84: Functional Scala II (in practice)

Mario Gleichmann JUG Frankfurt / Main84

Type Classes

def sum [A] ( xs : List[A], m: Monoid[A] ) : A =

xs match { case Nil => m.unit case head :: tail => m.add( head, sum( tail, m) )

}

Page 85: Functional Scala II (in practice)

Mario Gleichmann JUG Frankfurt / Main85

Type Classes

def sum [A] ( xs : List[A], m: Monoid[A] ) : A =

xs match { case Nil => m.unit case head :: tail => m.add( head, sum( tail, m) )

}

'type constraint'

Page 86: Functional Scala II (in practice)

Mario Gleichmann JUG Frankfurt / Main86

Type Classes

object IntMonoid extends Monoid[Int]{

def add(x : Int, y : Int): Int = x + y

def unit : Int = 0}

sum( List( 1, 2, 3, 4 ), IntMonoid )

Page 87: Functional Scala II (in practice)

Mario Gleichmann JUG Frankfurt / Main87

Type Classes

def sum [A] ( xs : List[A] ) ( implicit m: Monoid[A] ) : A = ...

implicit object IntMonoid extends Monoid[Int]{ … }

import typeclasses.monoid._...

sum( List( 1, 2, 3, 4 ) )

Page 88: Functional Scala II (in practice)

Mario Gleichmann JUG Frankfurt / Main88

Example: Clock-Monoid

sealed abstract case class ClockHour( hour: Int )case object HOUR_0 extends ClockHour( 0 )case object HOUR_1 extends ClockHour( 1 )...case object HOUR_11 extends ClockHour( 11 )

…implicit object ClockHourMonoid extends Monoid[ClockHour]{ val hours = Array( HOUR_0, HOUR_1, HOUR_2, ..., HOUR_11 ) def add(x : ClockHour, y : ClockHour) = hours( ( x.hour + y.hour ) % 12 ) def unit : ClockHour = HOUR_0}

Page 89: Functional Scala II (in practice)

Mario Gleichmann JUG Frankfurt / Main89

Example: Clock-Monoid

import typeclasses.monoid.ClockHourMonoid...

sum( List( HOUR_5, HOUR_3, HOUR_8 ) )

>> HOUR_4

Page 90: Functional Scala II (in practice)

Mario Gleichmann JUG Frankfurt / Main90

Example: Contains element ?

trait Eq[E]{ def equals( e1 :E, e2 :E ) : Boolean}

def contains [T] ( x :T, xs : List[T] ) ( implicit eq :Eq[T] ) : Boolean = reduce

( ( y :T ) => ( acc :Boolean ) =>

if( eq.equals( x, y ) ) true else acc )( false )

( xs ) 2nd Arg: 'unit'

3rd Arg: List to reduce

1st Arg: 'reducing' function

Page 91: Functional Scala II (in practice)

Mario Gleichmann JUG Frankfurt / Main91

Example: Contains element ?

case class Person( name :String, age :Int ) implicit object PersonEq extends Eq[Person]{ def equals( p1 :Person, p2 :Person ) : Boolean =

(p1.name == p2.name) && (p1.age == p2.age)} ...val persons = List( Person("Hans", 22),

Person( "Helga", 32 ), Person( "Hugo", 47 ) )

contains( Person( "Olga", 22 ), persons ) >> falsecontains( Person( "Helga", 32 ), persons ) >> true

Page 92: Functional Scala II (in practice)

Mario Gleichmann JUG Frankfurt / Main92

Monads

Page 93: Functional Scala II (in practice)

Mario Gleichmann JUG Frankfurt / Main

Monads

A simple Monad: Option

Option[+A]

<< abstract >>

Some[+A] None

presence absence Handling the or of something

...as the result of a computation (computational environment)

Page 94: Functional Scala II (in practice)

Mario Gleichmann JUG Frankfurt / Main

Monads

A simple Monad: Option

class CustomerDAO{

def findCustomer( custId: Long ) : Option<Customer> = { ... if( found( customer ) ) Some( customer ) else None } }

Page 95: Functional Scala II (in practice)

Mario Gleichmann JUG Frankfurt / Main

Monads

A simple Monad: Option

class CustomerDAO{

def findCustomer( custId: Long ) : Option<Customer> = { ... if( found( customer ) ) Some( customer ) else None } }

Explicit Notion, that there may be 'none' result

Page 96: Functional Scala II (in practice)

Mario Gleichmann JUG Frankfurt / Main

Monads

val customerHit = customerDAO.findCustomer( 123 );...

customerHit match {

case Some( customer ) => println( customer.name )

case None => println( “not found“ )}

A simple Monad: Option

Page 97: Functional Scala II (in practice)

Mario Gleichmann JUG Frankfurt / Main

Monads

val customerHit = customerDAO.findCustomer( 123 );...

customerHit match {

case Some( customer ) => println( customer.name )

case None => println( “not found“ )}

A simple Monad: Option

Explicit Handling the absensce of a result

Forces 'Awareness'

Page 98: Functional Scala II (in practice)

Mario Gleichmann JUG Frankfurt / Main

Monads

val customerHit = customerDAO.findCustomer( 123 );...

customerHit match {

case Some( customer ) => println( customer.name )

case None => println( “not found“ )}

A simple Monad: Option

... beside from that ... what's the deal ???

Page 99: Functional Scala II (in practice)

Mario Gleichmann JUG Frankfurt / Main

Monads

val customerHit = customerDAO.findCustomer( 123 );...

customerHit match {

case Some( customer ) => println( customer.name )

case None => println( “not found“ )}

A simple Monad: Option

'Protected' Function Composition ...

Page 100: Functional Scala II (in practice)

Mario Gleichmann JUG Frankfurt / Main

Monads

val projects = Map( "Jan" -> "IKT", "Joe" -> "TensE", "Luca" -> "InTA" ) val customers = Map( "IKT" -> "Hanso GmbH", "InTA" -> "RAIA Duo" ) val cities = Map( "Hanso GmbH" -> "Stuttgart", "Mogno" -> "Mailand" )

Page 101: Functional Scala II (in practice)

Mario Gleichmann JUG Frankfurt / Main

Monads

Where is Jan ? Jan -> IKT -> Hanso GmbH -> Stuttgart

val projects = Map( "Jan" -> "IKT", "Joe" -> "TensE", "Luca" -> "InTA" ) val customers = Map( "IKT" -> "Hanso GmbH", "InTA" -> "RAIA Duo" ) val cities = Map( "Hanso GmbH" -> "Stuttgart", "Mogno" -> "Mailand" )

Page 102: Functional Scala II (in practice)

Mario Gleichmann JUG Frankfurt / Main

Monads

public String whereIs( String name ){String project = projects.get( name );if( project != null ){

String customer = customers.get( project );if( customer != null ){

String city = cities.get( customer )if( city != null ) return city; else return “unknown“;

}else return ''unknown'';

}else return ''unknown'';

}

Java

Page 103: Functional Scala II (in practice)

Mario Gleichmann JUG Frankfurt / Main

Monads

def whereIs( name: String ) = { projects.get( name ) .flatMap( project => customers get project ) .flatMap( customer => cities get customer )

.getOrElse( "unknown!" )}

ScalaA simple Monad: Option

Page 104: Functional Scala II (in practice)

Mario Gleichmann JUG Frankfurt / Main

Monads

def whereIs( name: String ) = { projects.get( name ) .flatMap( project => customers get project ) .flatMap( customer => cities get customer )

.getOrElse( "unknown!" )}

ScalaA simple Monad: Option

Results in Option[String]

Page 105: Functional Scala II (in practice)

Mario Gleichmann JUG Frankfurt / Main

Monads

def whereIs( name: String ) = { projects.get( name ) .flatMap( project => customers get project ) .flatMap( customer => cities get customer )

.getOrElse( "unknown!" )}

ScalaA simple Monad: Option

Results in Option[String]

Option[A].map( A => B ) >> Option[B]

Page 106: Functional Scala II (in practice)

Mario Gleichmann JUG Frankfurt / Main

Monads

def whereIs( name: String ) = { projects.get( name ) .flatMap( project => customers get project ) .flatMap( customer => cities get customer )

.getOrElse( "unknown!" )}

ScalaA simple Monad: Option

Results in Option[String]

Option[A].map( A => B ) >> Option[B] Option[A].map( A => Option[B] ) >> Option[Option[B]]

Page 107: Functional Scala II (in practice)

Mario Gleichmann JUG Frankfurt / Main

Monads

def whereIs( name: String ) = { projects.get( name ) .flatMap( project => customers get project ) .flatMap( customer => cities get customer )

.getOrElse( "unknown!" )}

ScalaA simple Monad: Option

Results in Option[String]

Option[A].map( A => B ) >> Option[B] Option[A].map( A => Option[B] ) >> Option[Option[B]] Option[A].flatMap( A => Option[B] ) >> Option[B]

Page 108: Functional Scala II (in practice)

Mario Gleichmann JUG Frankfurt / Main

Monads

Some[A] Some[B]

None

map( A => B ) map( B => C )

None

Some[C]

None

Some[D]

map( C => D )

. . .

Protected Composition

Page 109: Functional Scala II (in practice)

Mario Gleichmann JUG Frankfurt / Main

Monads

def whereIs( name: String ) = ( for( project <- projects get name;

customer <- customers get project; city <- cities get customer

) yield city

).getOrElse( "unknown!" )

A simple Monad: Option

Page 110: Functional Scala II (in practice)

Mario Gleichmann JUG Frankfurt / Main

Summary

● Currying

● Combinators

● Fundamental Functions

● Type classes

● Monads

Scala allows for ...

Page 111: Functional Scala II (in practice)

Mario Gleichmann JUG Frankfurt / Main111

Thank you !

Page 112: Functional Scala II (in practice)

Mario Gleichmann JUG Frankfurt / Main112

References

Scala Home www.scala-lang.org

Dr. Erik Meijer C9 Lectures – Functional Programming Fundamentalshttp://channel9.msdn.com

Graham Hutton Programming in HaskellCambridge

Odersky, Spoon, Venners Programming in Scalaartima