lazy evaluation

67
lazy evaluation hey, i’m fronx. berlin compiler meetup, feb 2014

Upload: fronx-wurmus

Post on 29-Aug-2014

413 views

Category:

Technology


0 download

DESCRIPTION

 

TRANSCRIPT

Page 1: Lazy evaluation

lazy evaluationhey, i’m fronx.

berlin compiler meetup, feb 2014

Page 2: Lazy evaluation
Page 3: Lazy evaluation

bottom

infinite lists

approximation

eager

strictness in an argument

graph reduction

leftmost outermost

normal order

sharing

full laziness

WHNF

thunk

call by need

redex

constant subexpression

instantiation

Page 4: Lazy evaluation

not

- user-code performance optimization

- how and why to avoid capture

- supercombinators / λ-lifting

- representation in memory

- garbage collection

- compiler optimizations

Page 5: Lazy evaluation

http://research.microsoft.com/en-us/um/people/simonpj/papers/slpj-book-1987/

Page 6: Lazy evaluation

semantics

evaluation strategy

strict non-strict

eager lazy

vs.

Page 7: Lazy evaluation

as a language property

Page 8: Lazy evaluation

expressions can

have a value

even if some of their subexpressions

do nothttp://www.haskell.org/haskellwiki/Non-strict_semantics

non-strict

Page 9: Lazy evaluation

expressions can

have a value

even if some of their subexpressions

do nothttp://www.haskell.org/haskellwiki/Non-strict_semantics

strictnot

Page 10: Lazy evaluation

expressions can

have a value

even if some of their subexpressions

do nothttp://www.haskell.org/haskellwiki/Non-strict_semantics

strictnot

… have a value

Page 11: Lazy evaluation

“not have a value”?

Page 12: Lazy evaluation

loop :: Int -> Int loop n = 1 + loop n

Page 13: Lazy evaluation

loop :: Int -> Int loop n = 1 + loop n

repeat :: Int -> [Int] repeat n = n : repeat n !

> repeat 1 [1,1,1,1,1,1,1,1,1,1,1,1,…

Page 14: Lazy evaluation

how is this useful?

Page 15: Lazy evaluation

infinite lists are awesome.

nat :: [Int] nat = nat' 1 where nat' n = n : nat' (n + 1) !

take 5 (map sqr nat) == [1,4,9,16,25]

Page 16: Lazy evaluation

http://mybroadband.co.za/news/wp-content/uploads/2013/03/Barack-Obama-Michelle-Obama-not-bad.jpg

Page 17: Lazy evaluation

⊥”bottom”

“a computation which never completes successfully”

http://www.haskell.org/haskellwiki/Bottom

Page 18: Lazy evaluation

bottom :: a bottom = bottom

undefined (throws error)

Page 19: Lazy evaluation

take 0 _ = []

take n (x : xs) = x : take (n - 1) xs

take n [] = []

!

take 2 (1:1:1:undefined) == take 2 (1:1:undefined) == [1,1]

Page 20: Lazy evaluation

repeat n = n : repeat n !

repeat 1 => 1 : ⊥ => 1 : 1 : ⊥ => 1 : 1 : 1 : ⊥ => 1 : 1 : 1 : 1 : ⊥ …

Page 21: Lazy evaluation

repeat n = n : repeat n !

repeat 1 => 1 : ⊥ => 1 : 1 : ⊥ => 1 : 1 : 1 : ⊥ => 1 : 1 : 1 : 1 : ⊥ …

Terms

approximation,

more defined

http://en.wikibooks.org/wiki/Haskell/Denotational_semantics

Page 22: Lazy evaluation

strict / non-strict functions

Page 23: Lazy evaluation

a function is strict iff

f ⊥ = ⊥

Page 24: Lazy evaluation

strictness of functions

id = λ x . x

( λ x . x ) ⊥ = ⊥

strict

Page 25: Lazy evaluation

strictness of functions

one = λ x . 1

( λ x . 1 ) ⊥ = 1

non-strict

Page 26: Lazy evaluation

strictness of functions

second = λ x y . y

( λ x y . y ) ⊥ 2 = 2

non-strict

strict in its 2nd argument

in its 1st argument

Page 27: Lazy evaluation

repeat n = n : repeat n !

repeat 1 => 1 : ⊥ => 1 : 1 : ⊥ => 1 : 1 : 1 : ⊥ => 1 : 1 : 1 : 1 : ⊥ …

Question: Is repeat strict or non-strict

(“lazy”)?

Page 28: Lazy evaluation

repeat n = n : repeat n !

repeat ⊥ = ⊥ : repeat ⊥

Page 29: Lazy evaluation

repeat n = n : repeat n !

repeat ⊥ = ⊥ : repeat ⊥

strict

Page 30: Lazy evaluation

one x = 1 one ⊥ = 1

non-strict

Page 31: Lazy evaluation

evaluation strategies

Page 32: Lazy evaluation

eager lazyfirst 1 (loop 2)

=>

first 1 (loop 2)

=>

first x y = x

Page 33: Lazy evaluation

eager lazyfirst 1 (loop 2)

=> first 1 (2 + (loop 2))

=> first 1 (2 + (2 + (loop 2)))

=

first 1 (loop 2)

= 1

first x y = x

Page 34: Lazy evaluation

eager lazyfirst 1 (loop 2)

=> first 1 (2 + (loop 2))

=> first 1 (2 + (2 + (loop 2)))

=

first 1 (loop 2)

= 1

first x y = x

⊥redex: reducible expression

Page 35: Lazy evaluation

eager lazyfirst (loop 1) 2

=> first (1 + (loop 1)) 2

=> first (1 + (1 + (loop 1))) 2

=

first (loop 1) 2

=> loop 1

=> 1 + (loop 1)

=> 1 + (1 + (loop 1))

=

first x y = x

⊥⊥

Page 36: Lazy evaluation

eager lazynat 1

=>

nat 1

=>

nat n = n : nat (n + 1)

Page 37: Lazy evaluation

eager lazynat 1

=> 1 : nat (1+1)

=> 1 : nat 2

=> 1 : 2 : nat (2 + 1)

=

nat 1

= 1 : nat (1 + 1)

nat n = n : nat (n + 1)

the function is still strict! lazy evaluation allows

you to look at intermediate results, though.

Page 38: Lazy evaluation

eager lazynat 1

=> 1 : nat (1+1)

=> 1 : nat 2

=> 1 : 2 : nat (2 + 1)

=

nat 1

= 1 : nat (1 + 1)

nat n = n : nat (n + 1)

Question: How do you define the

point where it has to stop?

Page 39: Lazy evaluation

weak head normal form

expression head is one of:

- variable - data object - built-in function - lambda abstraction

http://research.microsoft.com/en-us/um/people/simonpj/papers/slpj-book-1987/

Page 40: Lazy evaluation

weak head normal form

An expression has no top-level redex

iff it is in

weak head normal form.

http://research.microsoft.com/en-us/um/people/simonpj/papers/slpj-book-1987/

Page 41: Lazy evaluation

weak head normal form

examples:

3 1 : (2 : …) == CONS 1 (CONS 2 …) + (- 4 3) (λx. + 5 1)

http://research.microsoft.com/en-us/um/people/simonpj/papers/slpj-book-1987/

Page 42: Lazy evaluation

weak head normal form

Ignore inner redexes as long as you can.

http://research.microsoft.com/en-us/um/people/simonpj/papers/slpj-book-1987/

result:

Page 43: Lazy evaluation

graph reductiona way to model / implement

lazy evaluation

Page 44: Lazy evaluation

first = λ x y . x first = λ x . λ y . x first 1 ⊥ @

λx

λy

x

@

1⊥

graph reduction

Page 45: Lazy evaluation

first = λ x y . x first = λ x . λ y . x first 1 ⊥ @

λx

λy

x

@

1⊥

graph reduction

leftmost outermost reduction

= normal-order

reduction

Page 46: Lazy evaluation

first = λ x y . x first = λ x . λ y . x first 1 ⊥ @

λx

λy

x

@

1⊥

@

λy

1

1

graph reduction

instantiate the lambda

body

Page 47: Lazy evaluation

sqr = λ x . x * x sqr 2 @

λx

@

@

2

graph reduction

* x

x

@

@

* 2

2

4

Page 48: Lazy evaluation

sqr (6 + 1)

@

λx

@

@

@

graph reduction

* x

x

@

+ 6

1

Page 49: Lazy evaluation

sqr (6 + 1)

@

λx

@

@

@

graph reduction

* x

x

@

@

*

@

+ 6

1

@

@

+ 6

1

@

@

+ 6

1

call by name

Page 50: Lazy evaluation

sqr (6 + 1)

@

λx

@

@

@

graph reduction

* x

x

@

+ 6

1

@

@@

*@

+ 6

1 @

@ 7*

49

sharing

call by need

Page 51: Lazy evaluation

+ call by name + sharing + —————— + call by need

Page 52: Lazy evaluation

( λ x . λ x . x ) 1 2

@

λx

λx

@

shadowing

x

1

2 @

λx

x

2

2

Page 53: Lazy evaluation

full lazinessλy. + y (sqrt 4)

@λy

@@

λx

@

“x(1), x(2)”

+ y sqrt 4

constant subexpression

http://research.microsoft.com/en-us/um/people/simonpj/papers/slpj-book-1987/

Page 54: Lazy evaluation

maximal free expression

a free expression which is not a subexpression

of another free expression

http://research.microsoft.com/en-us/um/people/simonpj/papers/slpj-book-1987/

Page 55: Lazy evaluation

full lazinessλy. + y (sqrt 4)

@λy

@@

λx

@

“x(1), x(2)”

+ y sqrt 4

maximal free expression in $

$

free subexpression

http://research.microsoft.com/en-us/um/people/simonpj/papers/slpj-book-1987/

Page 56: Lazy evaluation

full lazinessλy. + y (sqrt 4)

@λy

@

@λx

@

“x(1), x(2)”

+ y

sqrt 4

Extract all the maximal free expressions! !

|o/sqrt4

http://research.microsoft.com/en-us/um/people/simonpj/papers/slpj-book-1987/

Page 57: Lazy evaluation

full laziness

A Unified Approach to Fully Lazy Sharing, Balabonski 2012

fully lazy λ-lifting

extract MFEs via closures

sharing via labelling

variants

(sorry, no time for details.)

SPJ87

Sestoft97

Blanc/Levy/Maranget07

Page 58: Lazy evaluation

so how does take work?

take 0 _ = []

take n (x : xs) = x : take (n - 1) xs

take n [] = []

Page 59: Lazy evaluation

so how does take work?

take 0 _ = []

take n (x : xs) = x : take (n - 1) xs

take n [] = []

patterns

- variable - constant - sum constructor - product constructor

Page 60: Lazy evaluation

product-matching

= zeroPair (x,y) = 0

!

= Eval [[ zeroPair ]] ⊥ = ⊥

= Eval [[ zeroPair ]] ⊥ = 0 lazy product-matching

strict product-matching

http://research.microsoft.com/en-us/um/people/simonpj/papers/slpj-book-1987/

Page 61: Lazy evaluation

lazy product-matching

= zeroPair (x,y) = 0

!

= Eval [[ zeroPair ]] ⊥

= Eval [[ λ(Pair x y). 0 ]] ⊥

= Eval [[ λx. λy. 0 ]] (SEL-PAIR-1 ⊥) (SEL-PAIR-2 ⊥)

= Eval [[ λy. 0 ]] (SEL-PAIR-2 ⊥)

= 0

http://research.microsoft.com/en-us/um/people/simonpj/papers/slpj-book-1987/

Page 62: Lazy evaluation

lazy product-matching

SEL-PAIR-1 (Pair x y) = x

SEL-PAIR-1 ⊥ = ⊥

SEL-PAIR-2 (Pair x y) = y

SEL-PAIR-2 ⊥ = ⊥

http://research.microsoft.com/en-us/um/people/simonpj/papers/slpj-book-1987/

Page 63: Lazy evaluation

lazy product-matching

SEL-PAIR-1 (Pair x y) = x

SEL-PAIR-1 ⊥ = ⊥

SEL-PAIR-2 (Pair x y) = y

SEL-PAIR-2 ⊥ = ⊥

SEL-constr-i (constr a1 … ai … an) = ai

SEL-constr-i ⊥ = ⊥

http://research.microsoft.com/en-us/um/people/simonpj/papers/slpj-book-1987/

Page 64: Lazy evaluation

summary

- f is strict ⇔ f ⊥ = ⊥

- graph reduction

- sharing

- lazy pattern-matching

- go and read those papers/books

Page 65: Lazy evaluation

okay. that’s it for today.

Page 66: Lazy evaluation

http://www.techworld.com.au/article/261007/a-z_programming_languages_haskell/?pp=7

“Laziness kept us pure.”

Simon Peyton Jones

Page 67: Lazy evaluation

https://twitter.com/evilhaskelltips/status/429788191613140992

“If your program is slow, don't bother profiling. Just scatter bang patterns throughout your code like confetti.

They're magic!”