Lazy evaluation illustrated - GitHub Pages · One of the mental models for Haskell program main =...

215
Lazy evaluation illustrated for Haskell divers Takenobu T. Rev. 0.01.0 exploring some mental models and implementations WIP

Transcript of Lazy evaluation illustrated - GitHub Pages · One of the mental models for Haskell program main =...

Page 1: Lazy evaluation illustrated - GitHub Pages · One of the mental models for Haskell program main = exp aa (exp ab exp ac exp ad) exp ac = exp aca exp acb exp ad = exp ada exp adb exp

Lazy evaluation illustratedfor Haskell divers

Takenobu T.

Rev. 0.01.0

exploring some mental models and implementations

WIP

Page 2: Lazy evaluation illustrated - GitHub Pages · One of the mental models for Haskell program main = exp aa (exp ab exp ac exp ad) exp ac = exp aca exp acb exp ad = exp ada exp adb exp

Lazy,...

..., It’s fun!

Page 3: Lazy evaluation illustrated - GitHub Pages · One of the mental models for Haskell program main = exp aa (exp ab exp ac exp ad) exp ac = exp aca exp acb exp ad = exp ada exp adb exp

NOTE- Meaning of terms are different for each community.- There are a lot of good documents. Please see also references.- This is written for GHC’s Haskell.

Page 4: Lazy evaluation illustrated - GitHub Pages · One of the mental models for Haskell program main = exp aa (exp ab exp ac exp ad) exp ac = exp aca exp acb exp ad = exp ada exp adb exp

1. Introduction

- Basic mental models

- Lazy evaluation

- Simple questions

2. Expressions

- Expression and value

- Expressions in Haskell

- Classification by values and forms

- WHNF

3. Internal representation of expressions

- Constructor

- Thunk

- Uniform representation

- WHNF

- let, case expression

4. Evaluation

- Evaluation strategies

- Evaluation in Haskell (GHC)

- Examples of evaluation steps

- Examples of evaluations

- Controlling the evaluation

5. Implementation of evaluator

- Lazy graph reduction

- STG-machine

6. Semantics

- Bottom

- Strict/Non-strict

- Lifted and boxed types

- Strictness analysis

- Sequential order

7. Appendix

- References

Contents

Page 5: Lazy evaluation illustrated - GitHub Pages · One of the mental models for Haskell program main = exp aa (exp ab exp ac exp ad) exp ac = exp aca exp acb exp ad = exp ada exp adb exp

1. Introduction

Page 6: Lazy evaluation illustrated - GitHub Pages · One of the mental models for Haskell program main = exp aa (exp ab exp ac exp ad) exp ac = exp aca exp acb exp ad = exp ada exp adb exp

Basic mental models

1. Introduction

Page 7: Lazy evaluation illustrated - GitHub Pages · One of the mental models for Haskell program main = exp aa (exp ab exp ac exp ad) exp ac = exp aca exp acb exp ad = exp ada exp adb exp

How to evaluate a program in your brain ?

a program

code

code

code

:

How to evaluate (execute, reduce) the program in your brain?

What “mental model” do you have?

1. Introduction

Page 8: Lazy evaluation illustrated - GitHub Pages · One of the mental models for Haskell program main = exp aa (exp ab exp ac exp ad) exp ac = exp aca exp acb exp ad = exp ada exp adb exp

One of the mental models for C program

main (...) {

code..

code..

code..

code..

}

A sequence of statements

How to evaluate (execute, reduce) the program in your brain?

What step, what order, ... ?

x = func1( func2( a ) );

y = func1( a(x), b(x), c(x) );

z = func1( m + n );

A nested structure

A sequence of arguments

A function and arguments

C program

1. Introduction

Page 9: Lazy evaluation illustrated - GitHub Pages · One of the mental models for Haskell program main = exp aa (exp ab exp ac exp ad) exp ac = exp aca exp acb exp ad = exp ada exp adb exp

One of the mental models for C program

main (...) {

code..

code..

code..

code..

}

A program is a collection of statements.

Statements are

executed downward.

x = func1( func2( a ) );

from inner to outer

y = func1( a(x), b(x), c(x) );

from left to right

z = func1( m + n );

arguments first

apply second

Each programmer has some mental models in their brain.

A sequence of statements A nested structure

A sequence of arguments

A function and arguments

C program

1. Introduction

Page 10: Lazy evaluation illustrated - GitHub Pages · One of the mental models for Haskell program main = exp aa (exp ab exp ac exp ad) exp ac = exp aca exp acb exp ad = exp ada exp adb exp

One of the mental models for C program

This is a syntactically straightforward model for programming languages.

Maybe, You have some implicit mental model in your brain for C program.

(1) A program is a collection of statements.

(2) There is the order between evaluations of elements.

(3) There is the order between termination and start of evaluations.

termination

start termination

code..

code..

code..

code..

x = func1( func2( a ) ); func1( a(x), b(x), c(x) ); z = func1( m + n );

code..

code..

func1( func2( a ) );

start

(an implicit sequential order model)

1. Introduction

Page 11: Lazy evaluation illustrated - GitHub Pages · One of the mental models for Haskell program main = exp aa (exp ab exp ac exp ad) exp ac = exp aca exp acb exp ad = exp ada exp adb exp

One of the mental models for Haskell program

How to evaluate (execute, reduce) the program in your brain?

What step, what order, ... ?

Haskell program

main = expaa (expab expac expad )

expac = expaca expacb

expad = expada expadb expadc

:

1. Introduction

Page 12: Lazy evaluation illustrated - GitHub Pages · One of the mental models for Haskell program main = exp aa (exp ab exp ac exp ad) exp ac = exp aca exp acb exp ad = exp ada exp adb exp

One of the mental models for Haskell program

main = expaa (expab expac expad )

expac = expaca expacb

expad = expada expadb expadc

:

A entire program is regarded as a single expression.

The subexpression is evaluated (reduced) in some order.

The evaluation is performed by replacement.

main

expaa expab expac expad

expada expadb expadcexpaca expacb

Haskell programA program is a collection of expressions.

main = expaa (expab (expaca expacb ) (expada expadb expadc) )

1. Introduction

Page 13: Lazy evaluation illustrated - GitHub Pages · One of the mental models for Haskell program main = exp aa (exp ab exp ac exp ad) exp ac = exp aca exp acb exp ad = exp ada exp adb exp

One of the mental models for Haskell program

(1) A program is a collection of expressions.

(2) A entire program is regarded as a single expression.

(3) The subexpressions are evaluated (reduced) in some order.

main = e (e (e (e e) e (e e e) ) )

(4) The evaluation is performed by replacement.

f = e (e (e (e e) e (e e e) ) )

This is an example of an expression reduction model for Haskell.

1. Introduction

3+2 5

+ 3 2

Page 14: Lazy evaluation illustrated - GitHub Pages · One of the mental models for Haskell program main = exp aa (exp ab exp ac exp ad) exp ac = exp aca exp acb exp ad = exp ada exp adb exp

Lazy evaluation

1. Introduction

Page 15: Lazy evaluation illustrated - GitHub Pages · One of the mental models for Haskell program main = exp aa (exp ab exp ac exp ad) exp ac = exp aca exp acb exp ad = exp ada exp adb exp

To manipulate streames

pure is order free

2nd Church-Rosser theorem

...

fun

reactive

References : [H4], [H3], [B2], [B7], [B8], [D2], [D12], [D13], [D14]

Why lazy evaluation?

To manipulate infinite data structures

To manipulate huge data structures

potentially parallelism

out-of-order optimization

asynchronization

modularity

To implement non-strict semantics

There are various reasons

To avoid unnecessary computation

abstraction

amortizing

1. Introduction

Page 16: Lazy evaluation illustrated - GitHub Pages · One of the mental models for Haskell program main = exp aa (exp ab exp ac exp ad) exp ac = exp aca exp acb exp ad = exp ada exp adb exp

References : [B2] Ch.7, [H4] Ch.11, 12, [D2]

Haskell(GHC) ‘s lazy evaluation

+

evaluate only when needed

evaluate only enough

+

evaluate at most once

need

eval

eval

need

eval

need

no re-eval

Lazy evaluation

“Lazy” is “delay and avoidance” rather than “delay”.

1. Introduction

Page 17: Lazy evaluation illustrated - GitHub Pages · One of the mental models for Haskell program main = exp aa (exp ab exp ac exp ad) exp ac = exp aca exp acb exp ad = exp ada exp adb exp

+

+

References : [B2] Ch.7, [H4] Ch.11, 12, [D2]

Ingredient of Haskell(GHC) ‘s lazy evaluation

at most oncesubstitute pointers

update redex root with result

WHNF

evaluate

an expression

a value

only when needed normal order reduction

only enough stop at WHNF

This strategy is implemented by lazy graph reduction.

1. Introduction

Page 18: Lazy evaluation illustrated - GitHub Pages · One of the mental models for Haskell program main = exp aa (exp ab exp ac exp ad) exp ac = exp aca exp acb exp ad = exp ada exp adb exp

References : [B2] Ch.7, [H4] Ch.2, 11, 12, 15, [H5], [D2]

Techniques of Haskell(GHC) ‘s lazy evaluationevaluate

only when needed

evaluate

at most once

evaluate

only enough

self-updating modellazy constructor

normal order reduction(leftmost outermost reduction)

call-by-need

substitute pointers

full laziness

stop at WHNF

pattern-matching

lazy graph reduction

thunk

update redex root with result

1. Introduction

Page 19: Lazy evaluation illustrated - GitHub Pages · One of the mental models for Haskell program main = exp aa (exp ab exp ac exp ad) exp ac = exp aca exp acb exp ad = exp ada exp adb exp

Simple questions

1. Introduction

Page 20: Lazy evaluation illustrated - GitHub Pages · One of the mental models for Haskell program main = exp aa (exp ab exp ac exp ad) exp ac = exp aca exp acb exp ad = exp ada exp adb exp

References : [H4] Ch.2, 11, [B6] Ch.5

What order?

An expression is evaluated by normal order (leftmost outermost redex first).

exp0 exp1 exp2 expn...

an expression

To avoid unnecessary computation, normal order reduction chooses to apply the function

rather than first evaluating the argument.

Normal order reduction guarantees to find a normal form (if one exists).

1. Introduction

Page 21: Lazy evaluation illustrated - GitHub Pages · One of the mental models for Haskell program main = exp aa (exp ab exp ac exp ad) exp ac = exp aca exp acb exp ad = exp ada exp adb exp

How to postpone?

To postpone the evaluation, an unevaluated expression is built in the heap memory.

exp0 (exp1 exp2 exp3 )

heap memory

exp1 exp2 exp3

Haskell code

an unevaluated expression

build/allocate

References : [H4], [H5]

1. Introduction

thunk

Page 22: Lazy evaluation illustrated - GitHub Pages · One of the mental models for Haskell program main = exp aa (exp ab exp ac exp ad) exp ac = exp aca exp acb exp ad = exp ada exp adb exp

When needed?

Pattern-matching or forcing request drive the evaluation.

heap memory

exp1 exp2 exp3

pattern-matching

an unevaluated expression

evaluation request

case x of

Just _ -> True

Nothing -> False

seq x y

f $! arg

forcing request

x + y

built-in (primitive operation)

References : [H4], [D2], [D5]

1. Introduction

::

Page 23: Lazy evaluation illustrated - GitHub Pages · One of the mental models for Haskell program main = exp aa (exp ab exp ac exp ad) exp ac = exp aca exp acb exp ad = exp ada exp adb exp

References : [H4], [D2], [D5]

What to be careful about?

You can avoid the pitfalls by controlling the evaluation.

To consider hidden space leak

To consider performance cost to postpone unevaluated expressions

To consider evaluation (execution) order and timing in real world

heapmemory

heapmemory

build, force,

update, gc, ...

A

B

C

A

B

C

1. Introduction

Page 24: Lazy evaluation illustrated - GitHub Pages · One of the mental models for Haskell program main = exp aa (exp ab exp ac exp ad) exp ac = exp aca exp acb exp ad = exp ada exp adb exp

2. Expressions

Page 25: Lazy evaluation illustrated - GitHub Pages · One of the mental models for Haskell program main = exp aa (exp ab exp ac exp ad) exp ac = exp aca exp acb exp ad = exp ada exp adb exp

Expression and value

2. Expressions

Page 26: Lazy evaluation illustrated - GitHub Pages · One of the mental models for Haskell program main = exp aa (exp ab exp ac exp ad) exp ac = exp aca exp acb exp ad = exp ada exp adb exp

References : [B1] Ch.1, [B2] Ch.2, [B6] Ch.3, [H4] Ch.2

What is an expression?

?

An expression

2. Expressions

Page 27: Lazy evaluation illustrated - GitHub Pages · One of the mental models for Haskell program main = exp aa (exp ab exp ac exp ad) exp ac = exp aca exp acb exp ad = exp ada exp adb exp

References : [B1] Ch.1, [B2] Ch.2, [H1] Ch.1, [B6] Ch.3, [H4] Ch.2

An expression denotes a value

1 + 2

An expression

2. Expressions

Page 28: Lazy evaluation illustrated - GitHub Pages · One of the mental models for Haskell program main = exp aa (exp ab exp ac exp ad) exp ac = exp aca exp acb exp ad = exp ada exp adb exp

References : [B1] Ch.1, [B2] Ch.2, [H1] Ch.1, [B6] Ch.3, [H4] Ch.2

An expression is evaluated to a value

evaluate

A value

1 + 2

An expression

3

2. Expressions

Page 29: Lazy evaluation illustrated - GitHub Pages · One of the mental models for Haskell program main = exp aa (exp ab exp ac exp ad) exp ac = exp aca exp acb exp ad = exp ada exp adb exp

References : [B2] Ch.2, 7, [B6] Ch.3, [D1]

There are many evaluation approaches

( 1 + 2 ) ^ 2

An expression

A value

9

- Strict, Non-strict evaluation

- Eager, Lazy evaluation

- Call-by-value, Call-by-name,

Call-by-need, …

- Innermost, Outermost

- Normal order, Applicative order

- …

evaluation strategies

2. Expressions

Page 30: Lazy evaluation illustrated - GitHub Pages · One of the mental models for Haskell program main = exp aa (exp ab exp ac exp ad) exp ac = exp aca exp acb exp ad = exp ada exp adb exp

References : [D3], [B2] Ch.2, 7, [B6] Ch.3, [D1]

There are some evaluation levels

WHNF

take 3 [1..]

An expression

A value

[ 1, 2, 3 ]

NF

(Weak Head Normal Form)

(Normal Form)

2. Expressions

Page 31: Lazy evaluation illustrated - GitHub Pages · One of the mental models for Haskell program main = exp aa (exp ab exp ac exp ad) exp ac = exp aca exp acb exp ad = exp ada exp adb exp

Expressions in Haskell

2. Expressions

Page 32: Lazy evaluation illustrated - GitHub Pages · One of the mental models for Haskell program main = exp aa (exp ab exp ac exp ad) exp ac = exp aca exp acb exp ad = exp ada exp adb exp

References : [B2] Ch.2, [H1] Ch.3

There are many expressions in Haskell

if b then 1 else 0

Expressions

categorizing

x : xs

case x of _ -> 0

do {x <- get; put x}

﹨x -> x + 1

let x = 1 in x + y

fun arg

(﹨x -> x + 1) 3

7

‘a’

take 5 xs

Just 51 + 2

[1, 2, 3]

map f xs

(1, 2)

xs

2. Expressions

Page 33: Lazy evaluation illustrated - GitHub Pages · One of the mental models for Haskell program main = exp aa (exp ab exp ac exp ad) exp ac = exp aca exp acb exp ad = exp ada exp adb exp

References : [H1] Ch.3, [B2] Ch.2

Expression categories in Haskell

lambda abstraction let expression

conditional case expression do expression

variable

﹨x -> x + 1 let x = 1 in x + y

if b then 1 else 0 case x of _ -> 0 do {x <- get; put x}

general constructor, literal and some forms

7

‘a’

[1, 2, 3] (1, 2)

x : xs Just 5

function application

take 5 xs

map f xsfun arg

(﹨x -> x + 1) 3 1 + 2

xs

2. Expressions

Page 34: Lazy evaluation illustrated - GitHub Pages · One of the mental models for Haskell program main = exp aa (exp ab exp ac exp ad) exp ac = exp aca exp acb exp ad = exp ada exp adb exp

References : [H1] Ch.3, [B2] Ch.2

Specification is described in Haskell 2010 Language Report

“Haskell 2010 Language Report, Chapter 3 Expressions” [H1]

2. Expressions

Page 35: Lazy evaluation illustrated - GitHub Pages · One of the mental models for Haskell program main = exp aa (exp ab exp ac exp ad) exp ac = exp aca exp acb exp ad = exp ada exp adb exp

Classification by values and forms

2. Expressions

Page 36: Lazy evaluation illustrated - GitHub Pages · One of the mental models for Haskell program main = exp aa (exp ab exp ac exp ad) exp ac = exp aca exp acb exp ad = exp ada exp adb exp

References : [H5]

Classification by values

data values

Expressions

function values

values

unevaluated expressions

Values are data values or function values.

7

﹨x -> x + 1

Just 5

‘a’

[1, 2, 3] (1, 2)

let x = 1 in x + y

if b then 1 else 0 case x of _ -> 0 do {x <- get; put x}

take 5 xs

map f xs fun arg

(﹨x -> x + 1) 31 + 2

Just (f x)

bottom

2. Expressions

Page 37: Lazy evaluation illustrated - GitHub Pages · One of the mental models for Haskell program main = exp aa (exp ab exp ac exp ad) exp ac = exp aca exp acb exp ad = exp ada exp adb exp

References : [H4] Ch.11, [D3], [B6] Ch.3, [B2] Ch.2, 7, [D1], [W1]

Classification by forms

Expressions

Values are WHNF, HNF or NF.

WHNF

HNF ﹨x -> abs 1

unevaluated expressions

let x = 1 in x + y

if b then 1 else 0 case x of _ -> 0 do {x <- get; put x}

take 5 xs

map f xs fun arg

(﹨x -> x + 1) 31 + 2

values

bottom

NF

Just 5

‘a’

[1, 2, 3] (1, 2)

Just (f x)

7

﹨x -> x

﹨x -> x + (abs 1)[f x, g y]

2. Expressions

Page 38: Lazy evaluation illustrated - GitHub Pages · One of the mental models for Haskell program main = exp aa (exp ab exp ac exp ad) exp ac = exp aca exp acb exp ad = exp ada exp adb exp

WHNF

2. Expressions

Page 39: Lazy evaluation illustrated - GitHub Pages · One of the mental models for Haskell program main = exp aa (exp ab exp ac exp ad) exp ac = exp aca exp acb exp ad = exp ada exp adb exp

References : [H4] Ch.11, [D3], [B6] Ch.3, [B2] Ch.2, 7, [D1], [W1]

WHNF is one of the form in the evaluated values

WHNF

exp

An expression

A value

NF

NF

(Weak Head Normal Form)

(Normal Form)

(2) normal order reduction

of inner level redexes

no redexes at all

no top-level redexes

(1) normal order reduction

of top- level (head) redexes

2. Expressions

Page 40: Lazy evaluation illustrated - GitHub Pages · One of the mental models for Haskell program main = exp aa (exp ab exp ac exp ad) exp ac = exp aca exp acb exp ad = exp ada exp adb exp

References : [H4] Ch.11, [D3], [B5] Ch.2, [B4] Ch.24, [B6] Ch.3, [B2] Ch.2, 7, [D5], [D1]

WHNF

exp0 exp1 exp2 expn...

top-level (head) is

a constructor or

a lambda abstraction

no top-level redex

WHNF is a value which has evaluated top-level

2. Expressions

Page 41: Lazy evaluation illustrated - GitHub Pages · One of the mental models for Haskell program main = exp aa (exp ab exp ac exp ad) exp ac = exp aca exp acb exp ad = exp ada exp adb exp

References : [H4] Ch.11, [D3], [B5] Ch.2, [B4] Ch.24, [B6] Ch.3, [B2] Ch.2, 7, [D5], [D1]

WHNF for a data value and a function value

exp0 exp1 exp2 expn...

constructor

a data value in WHNFinner redexes

a function value in WHNF

﹨x1 .. xn -> exp

lambda abstraction

no top-level redex

inner redexes

no top-level redex

2. Expressions

Page 42: Lazy evaluation illustrated - GitHub Pages · One of the mental models for Haskell program main = exp aa (exp ab exp ac exp ad) exp ac = exp aca exp acb exp ad = exp ada exp adb exp

References : [H4] Ch.11, [D3], [B5] Ch.2, [B4] Ch.24, [B6] Ch.3, [B2] Ch.2, 7, [D5], [D1]

Examples of WHNF

Just (abs x)

Cons (f 1) (map f [2..] )

WHNF

no WHNF

Just 7

﹨x -> x + 1

if x then elseTrue False

abs 7

no top-level redex

top level-redex

no top-level redex

no top-level redex

no top-level redex

top level-redex

2. Expressions

Page 43: Lazy evaluation illustrated - GitHub Pages · One of the mental models for Haskell program main = exp aa (exp ab exp ac exp ad) exp ac = exp aca exp acb exp ad = exp ada exp adb exp

References : [H4] Ch.11, [D3], [B3]

HNF

exp0 exp1 exp2 expn...

* GHC uses WHNF rather than HNF.

no top-level redex

top-level (head) is

a constructor or

a lambda abstraction with no top-level redex

HNF is a value which has evaluated top-level

2. Expressions

Page 44: Lazy evaluation illustrated - GitHub Pages · One of the mental models for Haskell program main = exp aa (exp ab exp ac exp ad) exp ac = exp aca exp acb exp ad = exp ada exp adb exp

References : [H4] Ch.11, [D3], [B3]

HNF for a data value and a function value

exp0 exp1 exp2 expn...

constructor

a data value in HNFinner redexes

a function value in HNF

﹨x1 .. xn ->

lambda abstraction

(same as WHNF)

exp0 exp1 expn...

no redex

no top-level redex

2. Expressions

Page 45: Lazy evaluation illustrated - GitHub Pages · One of the mental models for Haskell program main = exp aa (exp ab exp ac exp ad) exp ac = exp aca exp acb exp ad = exp ada exp adb exp

References : [H4] Ch.11, [D3], [B3]

Examples of HNF

Just (abs x)HNF

no HNF

Just 7

abs 7

no top-level redex

top level-redex

no top-level redex

﹨x -> (abs 7)Just

no top-level redex

﹨x -> abs 7

top level-redex

2. Expressions

Page 46: Lazy evaluation illustrated - GitHub Pages · One of the mental models for Haskell program main = exp aa (exp ab exp ac exp ad) exp ac = exp aca exp acb exp ad = exp ada exp adb exp

References : [H4] Ch.11, [D3], [B5] Ch.2, [B4] Ch.24, [B6] Ch.3, [B2] Ch.2, 7, [D5], [D1]

NF

exp0 exp1 exp2 expn...

no internal redex

top-level (head) is

a constructor or

a lambda abstraction

NF is a value which has no redex.

2. Expressions

Page 47: Lazy evaluation illustrated - GitHub Pages · One of the mental models for Haskell program main = exp aa (exp ab exp ac exp ad) exp ac = exp aca exp acb exp ad = exp ada exp adb exp

References : [H4] Ch.11, [D3], [B5] Ch.2, [B4] Ch.24, [B6] Ch.3, [B2] Ch.2, 7, [D5], [D1]

NF for a data value and a function value

exp0 exp1 exp2 expn...

constructor

a data value in NF

a function value in NF

﹨x1 .. xn ->

lambda abstraction

exp0 exp1 expn...

no internal redex

no internal redex

2. Expressions

Page 48: Lazy evaluation illustrated - GitHub Pages · One of the mental models for Haskell program main = exp aa (exp ab exp ac exp ad) exp ac = exp aca exp acb exp ad = exp ada exp adb exp

References : [H4] Ch.11, [D3], [B5] Ch.2, [B4] Ch.24, [B6] Ch.3, [B2] Ch.2, 7, [D5], [D1]

Examples of NF

Cons 1

NF

no NF

Just 7

﹨x -> x + 1

no internal redex

﹨x ->

Nil

no internal redex

no internal redex

Just (abs 7)

redex

(abs 7)Just

redex

2. Expressions

Page 49: Lazy evaluation illustrated - GitHub Pages · One of the mental models for Haskell program main = exp aa (exp ab exp ac exp ad) exp ac = exp aca exp acb exp ad = exp ada exp adb exp

References : [H4] Ch.11, [D3], [B5] Ch.2, [B4] Ch.24, [B6] Ch.3, [B2] Ch.2, 7, [D5], [D1]

WHNF, HNF, NF

exp0 exp1 exp2 expn...

exp0 exp1 exp2 expn...

exp0 exp1 exp2 expn...WHNF

HNF

NF

no top-level redex

no top-level redex

no internal redex

top-level (head) is

a constructor or

a lambda abstraction with no top-level redex

top-level (head) is

a constructor or

a lambda abstraction

2. Expressions

Page 50: Lazy evaluation illustrated - GitHub Pages · One of the mental models for Haskell program main = exp aa (exp ab exp ac exp ad) exp ac = exp aca exp acb exp ad = exp ada exp adb exp

References : [H4] Ch.11

Definition of WHNF and HNF

“The implementation of functional programming languages” [H4]

2. Expressions

Page 51: Lazy evaluation illustrated - GitHub Pages · One of the mental models for Haskell program main = exp aa (exp ab exp ac exp ad) exp ac = exp aca exp acb exp ad = exp ada exp adb exp

3. Internal representation of expressions

Page 52: Lazy evaluation illustrated - GitHub Pages · One of the mental models for Haskell program main = exp aa (exp ab exp ac exp ad) exp ac = exp aca exp acb exp ad = exp ada exp adb exp

Constructor

3. Internal representation of expressions

Page 53: Lazy evaluation illustrated - GitHub Pages · One of the mental models for Haskell program main = exp aa (exp ab exp ac exp ad) exp ac = exp aca exp acb exp ad = exp ada exp adb exp

Constructor

Constructor is one of the key elements

to understand WHNF and lazy evaluation in Haskell.

3. Internal representation of expressions

Page 54: Lazy evaluation illustrated - GitHub Pages · One of the mental models for Haskell program main = exp aa (exp ab exp ac exp ad) exp ac = exp aca exp acb exp ad = exp ada exp adb exp

Constructor

exp0 exp1 exp2 expn...

constructor

A constructor builds a structured data value.

a data value

+

data components (n ≥ 0)(data constructor)

A constructor distinguishes the data value in expressions.

3. Internal representation of expressions

References : [B2], [H1], [H4] Ch.2, 10, [B6] Ch.11

Page 55: Lazy evaluation illustrated - GitHub Pages · One of the mental models for Haskell program main = exp aa (exp ab exp ac exp ad) exp ac = exp aca exp acb exp ad = exp ada exp adb exp

Constructors and data declaration

data Maybe a = Nothing

| Just a

constructor data component

Constructors are defined by data declaration.

3. Internal representation of expressions

References : [B2], [H1]

Page 56: Lazy evaluation illustrated - GitHub Pages · One of the mental models for Haskell program main = exp aa (exp ab exp ac exp ad) exp ac = exp aca exp acb exp ad = exp ada exp adb exp

Just

References : [H11], [H10], [H5], [H6], [H7]

Internal representation of Constructors for data values

Nothing

Just 7

Haskell code GHC’s internal representation

Nothing

header

header payload

7

heap memory

3. Internal representation of expressions

Page 57: Lazy evaluation illustrated - GitHub Pages · One of the mental models for Haskell program main = exp aa (exp ab exp ac exp ad) exp ac = exp aca exp acb exp ad = exp ada exp adb exp

References : [H11], [H10], [H5], [H6], [H7], [D15]

Constructors are represented uniformly

headerpayload

...

in heap memory, stack or static memory

object type data components

constructor,

function,

thunk, ...

GHC’s internal representation

A data value is represented with header(constructor) + payload(components).

3. Internal representation of expressions

Page 58: Lazy evaluation illustrated - GitHub Pages · One of the mental models for Haskell program main = exp aa (exp ab exp ac exp ad) exp ac = exp aca exp acb exp ad = exp ada exp adb exp

References : [H11], [H10], [H5], [H6], [H7]

Representation of various constructors

data Bool = False

| True

data Maybe a = Nothing

| Just a

data Either a b = Left a

| Right b

Just

Nothing

a

False

True

Left

a

Right

b

Haskell code GHC’s internal representation

3. Internal representation of expressions

Page 59: Lazy evaluation illustrated - GitHub Pages · One of the mental models for Haskell program main = exp aa (exp ab exp ac exp ad) exp ac = exp aca exp acb exp ad = exp ada exp adb exp

References : [H11], [H10], [H5], [H6], [H7]

Primitive data types are also represented with constructors

Haskell code

I# 0#

I# 1#

:

GHC’s internal representation

C# ‘a’#

C# ‘b’#

:

data Int = I# Int#

data Char = C# Char#

heap memory

1 :: Int

‘a’ :: Char

3. Internal representation of expressions

boxed integer unboxed integer

Page 60: Lazy evaluation illustrated - GitHub Pages · One of the mental models for Haskell program main = exp aa (exp ab exp ac exp ad) exp ac = exp aca exp acb exp ad = exp ada exp adb exp

List is also represented with constructors

[ 1, 2, 3 ]

syntactic desugar

1 : ( 2 : ( 3 : [] ) )

(:) 1 ( (:) 2 ( (:) 3 [] ) )

List

prefix notation by section

Cons 1 ( Cons 2 ( Cons 3 Nil ) )

equivalent data constructor

constructor

3. Internal representation of expressions

References : [H11], [H10], [H5], [H6], [H7]

Page 61: Lazy evaluation illustrated - GitHub Pages · One of the mental models for Haskell program main = exp aa (exp ab exp ac exp ad) exp ac = exp aca exp acb exp ad = exp ada exp adb exp

List is also represented with constructors

[ 1, 2, 3 ]

syntactic desugar

1 : ( 2 : ( 3 : [] ) )

(:) 1 ( (:) 2 ( (:) 3 [] ) )

List

prefix notation by section

Cons 1 ( Cons 2 ( Cons 3 Nil ) )

equivalent data constructor

* pseudo code

type declaration

data List a = Nil

| Cons a (List a)

data List a = []

| : a (List a)

3. Internal representation of expressions

References : [H11], [H10], [H5], [H6], [H7]

Page 62: Lazy evaluation illustrated - GitHub Pages · One of the mental models for Haskell program main = exp aa (exp ab exp ac exp ad) exp ac = exp aca exp acb exp ad = exp ada exp adb exp

References : [H11], [H10], [H5], [H6], [H7]

List is also represented with constructors

(:)

[]

Haskell code GHC’s internal representation

a List a

Cons

Nil

a List a

data List a = Nil

| Cons a (List a)

data List a = []

| : a (List a)

heap memory

* pseudo code

3. Internal representation of expressions

equivalent data constructor

Page 63: Lazy evaluation illustrated - GitHub Pages · One of the mental models for Haskell program main = exp aa (exp ab exp ac exp ad) exp ac = exp aca exp acb exp ad = exp ada exp adb exp

References : [H11], [H10], [H5], [H6], [H7]

List is also represented with constructors

[ 1, 2, 3 ]

1 : ( 2 : ( 3 : [] ) )

(:) 1 ( (:) 2 ( (:) 3 [] ) )

Cons 1 ( Cons 2 ( Cons 3 Nil ) )

Haskell code

GHC’s internal representation

1

Cons (:)

2

Cons (:)

3

Cons (:)

Nil ([])

3. Internal representation of expressions

Page 64: Lazy evaluation illustrated - GitHub Pages · One of the mental models for Haskell program main = exp aa (exp ab exp ac exp ad) exp ac = exp aca exp acb exp ad = exp ada exp adb exp

type declaration

Tuple is also represented with constructor

( 7, 8 )

(,) 7 8

Tuple (Pair)

prefix notation by section

Pair 7 8

equivalent data constructor

data Pair a = (,) a a

data Pair a = Pair a a

* pseudo code

constructor

3. Internal representation of expressions

References : [H11], [H10], [H5], [H6], [H7]

Page 65: Lazy evaluation illustrated - GitHub Pages · One of the mental models for Haskell program main = exp aa (exp ab exp ac exp ad) exp ac = exp aca exp acb exp ad = exp ada exp adb exp

References : [H11], [H10], [H5], [H6], [H7]

Tuple is also represented with constructor

(,)

Haskell code GHC’s internal representation

a a

Pair

a a

data Pair a = Pair a a

data Pair a = (,) a a

heap memory

3. Internal representation of expressions

equivalent data constructor

Page 66: Lazy evaluation illustrated - GitHub Pages · One of the mental models for Haskell program main = exp aa (exp ab exp ac exp ad) exp ac = exp aca exp acb exp ad = exp ada exp adb exp

References : [H11], [H10], [H5], [H6], [H7]

Tuple is also represented with constructor

( 7, 8 )

(,) 7 8

Pair 7 8

7

Pair (,)

8

Haskell code

GHC’s internal representation

3. Internal representation of expressions

Page 67: Lazy evaluation illustrated - GitHub Pages · One of the mental models for Haskell program main = exp aa (exp ab exp ac exp ad) exp ac = exp aca exp acb exp ad = exp ada exp adb exp

Thunk

3. Internal representation of expressions

Page 68: Lazy evaluation illustrated - GitHub Pages · One of the mental models for Haskell program main = exp aa (exp ab exp ac exp ad) exp ac = exp aca exp acb exp ad = exp ada exp adb exp

a thunk(an unevaluated expression/

a suspended computation)

References : [B5] Ch.2, [D5], [W1], [H10], [H5], [D7]

Thunk

A thunk is an unevaluated expression in heap memory.

A thunk is built to postpone the evaluation.

Haskell code GHC’s internal representation

an unevaluated expression

heap memory

3. Internal representation of expressions

Page 69: Lazy evaluation illustrated - GitHub Pages · One of the mental models for Haskell program main = exp aa (exp ab exp ac exp ad) exp ac = exp aca exp acb exp ad = exp ada exp adb exp

References : [H11], [H10], [D2], [H5], [H6], [H7], [B5] Ch.2, [D5], [W1]

Internal representation of a thunk

An unevaluated expressionheader

payload

y ys

thunk

info ptr

take y ys

code free variables

A thunk is represented with header(code) + payload(free variables).

Haskell code GHC’s internal representation

take y ys

3. Internal representation of expressions

Page 70: Lazy evaluation illustrated - GitHub Pages · One of the mental models for Haskell program main = exp aa (exp ab exp ac exp ad) exp ac = exp aca exp acb exp ad = exp ada exp adb exp

thunk

References : [D2], [H11], [H10], [H5], [H6], [H7], [B5] Ch.2, [D5], [W1]

A thunk is a package

info ptr

headerpayload

y ystake y ys

code free variables

A thunk is a package of code + free variables.

3. Internal representation of expressions

Page 71: Lazy evaluation illustrated - GitHub Pages · One of the mental models for Haskell program main = exp aa (exp ab exp ac exp ad) exp ac = exp aca exp acb exp ad = exp ada exp adb exp

References : [D7], [D2], [H11], [H10], [H5], [H6], [H7], [B5] Ch.2, [D5], [W1], [D15]

A thunk is evaluated by forcing request

Haskell code GHC’s internal representation

An unevaluated expressionheader

payload

y ys

thunk

info ptr

take y ys

code free variables

take y ys

[ 3 ]

An evaluated expression

evaluateby forcing request

Cons (:)

3 Nil ([])

evaluateby forcing request

3. Internal representation of expressions

Page 72: Lazy evaluation illustrated - GitHub Pages · One of the mental models for Haskell program main = exp aa (exp ab exp ac exp ad) exp ac = exp aca exp acb exp ad = exp ada exp adb exp

Uniform representation

3. Internal representation of expressions

Page 73: Lazy evaluation illustrated - GitHub Pages · One of the mental models for Haskell program main = exp aa (exp ab exp ac exp ad) exp ac = exp aca exp acb exp ad = exp ada exp adb exp

References : [H11], [H10], [H5], [H6], [H7], [D15]

Every object is uniformly represented in memory

headerpayload

...

in heap memory, stack or static memory

object type data components

constructor,

function,

thunk, ...

3. Internal representation of expressions

Page 74: Lazy evaluation illustrated - GitHub Pages · One of the mental models for Haskell program main = exp aa (exp ab exp ac exp ad) exp ac = exp aca exp acb exp ad = exp ada exp adb exp

References : [H11], [H10], [H5], [H6], [H7], [D15]

Every object is uniformly represented in memory

a thunka data value a function value

header payload

...

3. Internal representation of expressions

Page 75: Lazy evaluation illustrated - GitHub Pages · One of the mental models for Haskell program main = exp aa (exp ab exp ac exp ad) exp ac = exp aca exp acb exp ad = exp ada exp adb exp

References : [H11], [H10], [H5], [H6], [H7], [D15]

Every object is uniformly represented in memory

header payload

...

codefree variables

info ptrinfo ptrinfo ptr

a thunka data value a function value

codefree variables

stack or

registers

arguments

data componentsconstructor

3. Internal representation of expressions

* At exactly, a thunk object has

a reserved field in second.

Page 76: Lazy evaluation illustrated - GitHub Pages · One of the mental models for Haskell program main = exp aa (exp ab exp ac exp ad) exp ac = exp aca exp acb exp ad = exp ada exp adb exp

WHNF

3. Internal representation of expressions

Page 77: Lazy evaluation illustrated - GitHub Pages · One of the mental models for Haskell program main = exp aa (exp ab exp ac exp ad) exp ac = exp aca exp acb exp ad = exp ada exp adb exp

References : [H11], [H5], [H6], [H7], [H10]

Internal representation of WHNF

exp0 exp1 expn...

constructor

a data value in WHNF

a function value in WHNF

﹨x1 .. xn -> exp

lambda abstraction

info ptr

constructor

data component(s)

heap memory

info ptr

code

(exp) free variables

info ptr

...

info ptr

data component(s)

exp1

exp2

Haskell code GHC’s internal representation

3. Internal representation of expressions

Page 78: Lazy evaluation illustrated - GitHub Pages · One of the mental models for Haskell program main = exp aa (exp ab exp ac exp ad) exp ac = exp aca exp acb exp ad = exp ada exp adb exp

References : [H11], [H5], [H6], [H7], [H10]

Example of WHNF for a data value

Just (take x [1..])

constructor

Just

constructor

a redex

an unevaluated expression

Haskell code GHC’s internal representation

info ptr

take x [1..]x

thunk

free variables

Constructors can contain unevaluated expressions by thunks.

Haskell’s constructors are lazy constructors.

3. Internal representation of expressions

Page 79: Lazy evaluation illustrated - GitHub Pages · One of the mental models for Haskell program main = exp aa (exp ab exp ac exp ad) exp ac = exp aca exp acb exp ad = exp ada exp adb exp

References : [H11], [H5], [H6], [H7], [H10]

Example of WHNF for a data value

Cons (map f xs)

constructor

Cons

constructor

Haskell code GHC’s internal representation

info ptr

map f xsf

thunk

free variables

Nil

[ map f xs ]

syntactic desugar

xs

Nila redex

an unevaluated expression

3. Internal representation of expressions

Page 80: Lazy evaluation illustrated - GitHub Pages · One of the mental models for Haskell program main = exp aa (exp ab exp ac exp ad) exp ac = exp aca exp acb exp ad = exp ada exp adb exp

let, case expression

3. Internal representation of expressions

Page 81: Lazy evaluation illustrated - GitHub Pages · One of the mental models for Haskell program main = exp aa (exp ab exp ac exp ad) exp ac = exp aca exp acb exp ad = exp ada exp adb exp

let, case expression

let and case expressions are special role in the evaluation

3. Internal representation of expressions

Page 82: Lazy evaluation illustrated - GitHub Pages · One of the mental models for Haskell program main = exp aa (exp ab exp ac exp ad) exp ac = exp aca exp acb exp ad = exp ada exp adb exp

References : [H5], [H6], [H7], [H10]

let/case expressions and thunk

thunk(unevaluated expression/

suspended computation)

let expression case expression(allocate)

build

force

(evaluate)

extract

(deconstruct)

A let expression may build a thunk.

A case expression evaluates (forces) and deconstructs the thunk.

3. Internal representation of expressions

Page 83: Lazy evaluation illustrated - GitHub Pages · One of the mental models for Haskell program main = exp aa (exp ab exp ac exp ad) exp ac = exp aca exp acb exp ad = exp ada exp adb exp

References : [H5], [H6], [H7], [H10]

A let expression may allocates a heap object

let x = .....(build)

allocate

heap memory

let expression

a thunk

(an unevaluated expression)

a function value

a data value

or

or

* At exactly, STG language’s let expression rather than Haskell’s let expression

A let expression may allocates an object in the heap.(If GHC can optimize it, the let expression may not allocate.)

3. Internal representation of expressions

Page 84: Lazy evaluation illustrated - GitHub Pages · One of the mental models for Haskell program main = exp aa (exp ab exp ac exp ad) exp ac = exp aca exp acb exp ad = exp ada exp adb exp

References : [H5], [H6], [H7], [H10]

Example of let expressions

let x = Just 5

(build)

allocate

let x = ﹨y -> y + z

let x = take y ys

Just

5

info ptr

﹨y -> y + zfree variables

z

info ptr

take y ysfree variables

y

allocate

allocate

Haskell code GHC’s internal representation

ys

a data value

a function value

a thunk

3. Internal representation of expressions

Page 85: Lazy evaluation illustrated - GitHub Pages · One of the mental models for Haskell program main = exp aa (exp ab exp ac exp ad) exp ac = exp aca exp acb exp ad = exp ada exp adb exp

References : [H5], [H6], [H7], [H10], [D2]

A case expression evaluates a subexpression

case x of

pattern1 -> alt1

pattern2 -> alt2

heap memory

case expressiona data value or

a function value or

a thunk

* At exactly, STG language’s case expression rather than Haskell’s case expression

Pattern-matching drives the evaluation.

x

x

(1) pattern-matching drives

the evaluation

an evaluated value

(a data value or

a function value)

3. Internal representation of expressions

evaluate

Page 86: Lazy evaluation illustrated - GitHub Pages · One of the mental models for Haskell program main = exp aa (exp ab exp ac exp ad) exp ac = exp aca exp acb exp ad = exp ada exp adb exp

References : [H5], [H6], [H7], [H10], [D2]

A case expression also perform case analysis

case x of

pattern1 -> alt1

pattern2 -> alt2

heap memory

case expressiona data value or

a function value or

a thunk

* At exactly, STG language’s case expression rather than Haskell’s case expression

A case expression evaluates a subexpression

and optionally performs case analysis on its value.

x

x

(1) pattern-matching drives

the evaluation

(2) select alternative

expression

with result value

an evaluated value

(a data value or

a function value)

3. Internal representation of expressions

evaluate

Page 87: Lazy evaluation illustrated - GitHub Pages · One of the mental models for Haskell program main = exp aa (exp ab exp ac exp ad) exp ac = exp aca exp acb exp ad = exp ada exp adb exp

References : [H5], [H6], [H7], [H10], [D2]

Example of a case expression

case x of

Just _ -> True

Nothing -> False

(1) pattern-matching drives

the evaluation

heap memory

case expression

evaluate

(2) select alternative

expression

with result value

x

x

info ptr

f xsfree variables

f xs

a thunk

Just

5

A case expression’s pattern-matching says “I need the value”.

3. Internal representation of expressions

Page 88: Lazy evaluation illustrated - GitHub Pages · One of the mental models for Haskell program main = exp aa (exp ab exp ac exp ad) exp ac = exp aca exp acb exp ad = exp ada exp adb exp

References : [H1]

Pattern-matching in function definition

f Just _ = True

f Nothing = False

pattern-matching in function definition

f x = case x of

Just _ -> True

Nothing -> False

pattern-matching in case expression

syntactic desugar

A function’s pattern-matching also drives the evaluation.

A function’s pattern-matching is syntactic sugar of case expression.

3. Internal representation of expressions

Page 89: Lazy evaluation illustrated - GitHub Pages · One of the mental models for Haskell program main = exp aa (exp ab exp ac exp ad) exp ac = exp aca exp acb exp ad = exp ada exp adb exp

4. Evaluation

Page 90: Lazy evaluation illustrated - GitHub Pages · One of the mental models for Haskell program main = exp aa (exp ab exp ac exp ad) exp ac = exp aca exp acb exp ad = exp ada exp adb exp

Evaluation strategies

4. Evaluation

Page 91: Lazy evaluation illustrated - GitHub Pages · One of the mental models for Haskell program main = exp aa (exp ab exp ac exp ad) exp ac = exp aca exp acb exp ad = exp ada exp adb exp

References : [B1] Ch.1, [B2] Ch.2, [H1] Ch.1, [B6] Ch.3

Evaluation

evaluate

A value

1 + 2

An expression

3

4. Evaluation

The evaluation produces a value from an expression.

Page 92: Lazy evaluation illustrated - GitHub Pages · One of the mental models for Haskell program main = exp aa (exp ab exp ac exp ad) exp ac = exp aca exp acb exp ad = exp ada exp adb exp

References : [B3] Ch.2, 7, [B6] Ch.3, [D1]

There are many evaluation approaches

[ 1 + 2 ]

An expression

A value

[ 3 ]

- Strict, Non-strict evaluation

- Eager, Lazy evaluation

- Call-by-value, Call-by-name,

Call-by-need, …

- Innermost, Outermost

- Normal order, Application order

- …

evaluation strategies

4. Evaluation

Page 93: Lazy evaluation illustrated - GitHub Pages · One of the mental models for Haskell program main = exp aa (exp ab exp ac exp ad) exp ac = exp aca exp acb exp ad = exp ada exp adb exp

Evaluation concept layer

Implementation techniques

Operational semantics

(Evaluation strategies / Reduction strategies)

Denotational semantics

4. Evaluation

Page 94: Lazy evaluation illustrated - GitHub Pages · One of the mental models for Haskell program main = exp aa (exp ab exp ac exp ad) exp ac = exp aca exp acb exp ad = exp ada exp adb exp

References : [D3], [D1], [D2], [D5], [D4], [B2] Ch.7, [B3] Ch.8, [B6] Ch.5, [W1], [W2], [W3], [B7], [B8]

Evaluation layer for GHC’s Haskell

Implementation

techniques

Strict semantics Non-strict semantics

Strict evaluation Non-strict evaluation

Lazy graph reduction

Call-by-Value Call-by-Name Call-by-Need

...

...

...

Denotational

semantics

(Evaluation strategies/

Reduction strategies)

Operational

semantics

Applicative order reduction Normal order reduction

Tree reduction

...

Eager evaluation Lazy evaluationNondeterministic

evaluation

Innermost reduction Outermost reductionRightmost reduction Leftmost reduction

4. Evaluation

Page 95: Lazy evaluation illustrated - GitHub Pages · One of the mental models for Haskell program main = exp aa (exp ab exp ac exp ad) exp ac = exp aca exp acb exp ad = exp ada exp adb exp

References : [D3], [D1], [D2], [D5], [D4], [B2] Ch.7, [B3] Ch.8, [B6] Ch.5, [W1], [W2], [W3], [B7], [B8]

Evaluation layer for GHC’s Haskell

Implementation

techniques

Strict semantics Non-strict semantics

Strict evaluation Non-strict evaluation

Lazy graph reduction

Call-by-Value Call-by-Name Call-by-Need

...

...

...

Denotational

semantics

(Evaluation strategies/

Reduction strategies)

Operational

semantics

Applicative order reduction Normal order reduction

Tree reduction

...

Eager evaluation Lazy evaluationNondeterministic

evaluation

Innermost reduction Outermost reductionRightmost reduction Leftmost reduction

4. Evaluation

Page 96: Lazy evaluation illustrated - GitHub Pages · One of the mental models for Haskell program main = exp aa (exp ab exp ac exp ad) exp ac = exp aca exp acb exp ad = exp ada exp adb exp

References : [D3], [D1], [D2], [D5], [D4], [B2] Ch.7, [B3] Ch.8, [B6] Ch.5, [W1], [W2], [W3], [B7], [B8]

Evaluation strategies

Each evaluation strategy decides how to operate the evaluation, about ...

ordering,

region,

trigger condition,

termination condition,

re-evaluation, ...

4. Evaluation

Page 97: Lazy evaluation illustrated - GitHub Pages · One of the mental models for Haskell program main = exp aa (exp ab exp ac exp ad) exp ac = exp aca exp acb exp ad = exp ada exp adb exp

References : [D3], [D1], [D2], [D5], [D4], [B2] Ch.7, [B3] Ch.8, [B6] Ch.5, [W1], [W2], [W3], [B7], [B8]

One of the important points is the order

function arguments

which first?

eager evaluation,

call-by-value,

innermost reduction,

applicative order reduction

lazy evaluation,

call-by-name,

call-by-need,

outermost reduction,

normal order reduction

apply first argument first

4. Evaluation

apply

Page 98: Lazy evaluation illustrated - GitHub Pages · One of the mental models for Haskell program main = exp aa (exp ab exp ac exp ad) exp ac = exp aca exp acb exp ad = exp ada exp adb exp

References : [B2] Ch.7, [B3] Ch.8, [D4], [B6] Ch.5

Simple example of typical evaluations

call-by-value call-by-need

square ( 1 + 2 ) square ( 1 + 2 )

argument

evaluation

first

apply

first

4. Evaluation

Page 99: Lazy evaluation illustrated - GitHub Pages · One of the mental models for Haskell program main = exp aa (exp ab exp ac exp ad) exp ac = exp aca exp acb exp ad = exp ada exp adb exp

References : [B2] Ch.7, [B3] Ch.8, [D4], [B6] Ch.5

Simple example of typical evaluations

call-by-value call-by-need

square ( 1 + 2 ) square ( 1 + 2 )

square ( 3 ) ( 1 + 2 ) * ( 1 + 2 )

3 * 3 ( 3 ) * ( 3 )

9 9

evaluation is

delayed !

evaluation is

performed

4. Evaluation

Page 100: Lazy evaluation illustrated - GitHub Pages · One of the mental models for Haskell program main = exp aa (exp ab exp ac exp ad) exp ac = exp aca exp acb exp ad = exp ada exp adb exp

Evaluation in Haskell (GHC)

4. Evaluation

Page 101: Lazy evaluation illustrated - GitHub Pages · One of the mental models for Haskell program main = exp aa (exp ab exp ac exp ad) exp ac = exp aca exp acb exp ad = exp ada exp adb exp

References : [H4] Ch.11, 12, [H5], [H6], [D2]

Key concepts of GHC’s lazy evaluation

WHNF

An expression

A value

NF

fun args

postpone the evaluation of arguments

to evaluate only when needed

evaluate

stop at WHNF

to evaluate only enough

update itself

to evaluate at most once

drive the evaluation

by pattern-matching

4. Evaluation

reduce in normal order and

Page 102: Lazy evaluation illustrated - GitHub Pages · One of the mental models for Haskell program main = exp aa (exp ab exp ac exp ad) exp ac = exp aca exp acb exp ad = exp ada exp adb exp

References : [H5], [H6], [H10]

Postpone the evaluation of arguments

postpone the evaluation by a thunk which build with let expression

heap memory

Haskell code

postpone

info ptr

map g1 ys free variables

g1 ys

a thunk

fun (map g1 ys)

let thunk0 = map g1 ys

in fun thunk0

internal translation

(build)

4. Evaluation

(When GHC can optimize it by analysis, the thunk may not be build.)

Page 103: Lazy evaluation illustrated - GitHub Pages · One of the mental models for Haskell program main = exp aa (exp ab exp ac exp ad) exp ac = exp aca exp acb exp ad = exp ada exp adb exp

References : [H5], [H6], [H7], [H10], [D2]

Pattern-matching drives the evaluation

case x of

pattern1 -> alt1

pattern2 -> alt2

heap memory

case expression a thunkx

pattern-matching drives

the evaluation

4. Evaluation

evaluate

drive the evaluation by pattern-matching

Page 104: Lazy evaluation illustrated - GitHub Pages · One of the mental models for Haskell program main = exp aa (exp ab exp ac exp ad) exp ac = exp aca exp acb exp ad = exp ada exp adb exp

References : [H5], [H6], [H10]

Stop at WHNF4. Evaluation

WHNF

an unevaluated expression

evaluate

heap memory

info ptr

code free variables

a thunk

a value (WHNF)

evaluate

exp exp exp... ...

evaluated

info ptr

evaluated

Haskell code GHC’s internal representation

stop the evaluation at WHNF

Page 105: Lazy evaluation illustrated - GitHub Pages · One of the mental models for Haskell program main = exp aa (exp ab exp ac exp ad) exp ac = exp aca exp acb exp ad = exp ada exp adb exp

Examples of evaluation steps

4. Evaluation

Page 106: Lazy evaluation illustrated - GitHub Pages · One of the mental models for Haskell program main = exp aa (exp ab exp ac exp ad) exp ac = exp aca exp acb exp ad = exp ada exp adb exp

(1) Example of GHC’s evaluation

tail (map abs [1, -2, 3])

Let’s evaluate. It’s time to magic!

4. Evaluation

* no optimizing case (without –O)

Page 107: Lazy evaluation illustrated - GitHub Pages · One of the mental models for Haskell program main = exp aa (exp ab exp ac exp ad) exp ac = exp aca exp acb exp ad = exp ada exp adb exp

(2) How to postpone the evaluation of arguments?

tail (map abs [1, -2, 3])

function

argument

4. Evaluation

Page 108: Lazy evaluation illustrated - GitHub Pages · One of the mental models for Haskell program main = exp aa (exp ab exp ac exp ad) exp ac = exp aca exp acb exp ad = exp ada exp adb exp

(3) GHC internally translates the expression

tail (map abs [1, -2, 3])

let thunk0 = map abs [1, -2, 3]

in tail thunk0

internal translation

4. Evaluation

Page 109: Lazy evaluation illustrated - GitHub Pages · One of the mental models for Haskell program main = exp aa (exp ab exp ac exp ad) exp ac = exp aca exp acb exp ad = exp ada exp adb exp

(4) a let expression builds a thunk

tail (map abs [1, -2, 3])

let thunk0 = map abs [1, -2, 3]

in tail thunk0

thunk

map f xs abs [1,-2,3]

internal translationheap memory

build

4. Evaluation

Page 110: Lazy evaluation illustrated - GitHub Pages · One of the mental models for Haskell program main = exp aa (exp ab exp ac exp ad) exp ac = exp aca exp acb exp ad = exp ada exp adb exp

(5) function apply to argument

tail (map abs [1, -2, 3])

let thunk0 = map abs [1, -2, 3]

in tail thunk0

internal translation

thunk

map f xs abs [1,-2,3]

heap memory

apply

4. Evaluation

Page 111: Lazy evaluation illustrated - GitHub Pages · One of the mental models for Haskell program main = exp aa (exp ab exp ac exp ad) exp ac = exp aca exp acb exp ad = exp ada exp adb exp

tail (map abs [1, -2, 3])

let thunk0 = map abs [1, -2, 3]

in tail thunk0

internal translation

thunk

map f xs abs [1,-2,3]

heap memory

(6) tail function is defined here

tail (_:xs) = xs

4. Evaluation

definition

Page 112: Lazy evaluation illustrated - GitHub Pages · One of the mental models for Haskell program main = exp aa (exp ab exp ac exp ad) exp ac = exp aca exp acb exp ad = exp ada exp adb exp

tail (map abs [1, -2, 3])

let thunk0 = map abs [1, -2, 3]

in tail thunk0

internal translation

thunk

map f xs abs [1,-2,3]

heap memory

tail (_:xs) = xs

(7) function’s pattern is syntactic sugar

tail y = case y of

(_:xs) -> xs

syntactic

desugar

4. Evaluation

Page 113: Lazy evaluation illustrated - GitHub Pages · One of the mental models for Haskell program main = exp aa (exp ab exp ac exp ad) exp ac = exp aca exp acb exp ad = exp ada exp adb exp

tail (map abs [1, -2, 3])

let thunk0 = map abs [1, -2, 3]

in tail thunk0

internal translation

thunk

map f xs abs [1,-2,3]

heap memory

tail (_:xs) = xs

tail y = case y of

(_:xs) -> xs

(8) substitute the function body (beta reduction)

case thunk0 of

(_:xs) -> xs

reduction

4. Evaluation

Page 114: Lazy evaluation illustrated - GitHub Pages · One of the mental models for Haskell program main = exp aa (exp ab exp ac exp ad) exp ac = exp aca exp acb exp ad = exp ada exp adb exp

(9) case pattern-matching drives the evaluation

tail (map abs [1, -2, 3])

let thunk0 = map abs [1, -2, 3]

in tail thunk0

internal translation

thunk

map f xs abs [1,-2,3]

heap memory

tail (_:xs) = xs

tail y = case y of

(_:xs) -> xs

case thunk0 of

(_:xs) -> xs

evaluate

4. Evaluation

drive the evaluation

(forcing request)

Page 115: Lazy evaluation illustrated - GitHub Pages · One of the mental models for Haskell program main = exp aa (exp ab exp ac exp ad) exp ac = exp aca exp acb exp ad = exp ada exp adb exp

tail (map abs [1, -2, 3])

let thunk0 = map abs [1, -2, 3]

in tail thunk0

internal translation

thunk

map f xs abs [1,-2,3]

heap memory

tail (_:xs) = xs

tail y = case y of

(_:xs) -> xs

case thunk0 of

(_:xs) -> xs

(10) but, stop at WHNF

1

constructor

Cons

abs x map f xs abs [-2,3]

thunkthunk

stop at

WHNF

evaluate

4. Evaluation

case (abs 1) : (map abs [-2, 3]) of

(_:xs) -> xs

evaluated

Page 116: Lazy evaluation illustrated - GitHub Pages · One of the mental models for Haskell program main = exp aa (exp ab exp ac exp ad) exp ac = exp aca exp acb exp ad = exp ada exp adb exp

(11) bind variables to a result

tail (map abs [1, -2, 3])

let thunk0 = map abs [1, -2, 3]

in tail thunk0

internal translation

thunk

map f xs abs [1,-2,3]

heap memory

tail (_:xs) = xs

tail y = case y of

(_:xs) -> xs

case thunk0 of

(_:xs) -> xs

1

constructor

Cons

abs x map f xs abs [-2,3]

thunkthunk

evaluate

case (abs 1) : (map abs [-2, 3]) of

(_:xs) -> xs

4. Evaluation

Page 117: Lazy evaluation illustrated - GitHub Pages · One of the mental models for Haskell program main = exp aa (exp ab exp ac exp ad) exp ac = exp aca exp acb exp ad = exp ada exp adb exp

(12) return the value

tail (map abs [1, -2, 3])

let thunk0 = map abs [1, -2, 3]

in tail thunk0

internal translation

thunk

map f xs abs [1,-2,3]

heap memory

tail (_:xs) = xs

tail y = case y of

(_:xs) -> xs

case thunk0 of

(_:xs) -> xs

1

constructor

Cons

abs x map f xs abs [-2,3]

thunkthunk

evaluate

case (abs 1) : (map abs [-2, 3]) of

(_:xs) -> xs

map abs [-2, 3]

a result value

4. Evaluation

Page 118: Lazy evaluation illustrated - GitHub Pages · One of the mental models for Haskell program main = exp aa (exp ab exp ac exp ad) exp ac = exp aca exp acb exp ad = exp ada exp adb exp

Key points

tail (map abs [1, -2, 3])

let thunk0 = map abs [1, -2, 3]

in tail thunk0

internal translation

thunk

map f xs abs [1,-2,3]

heap memory

tail (_:xs) = xs

tail y = case y of

(_:xs) -> xs

case thunk0 of

(_:xs) -> xs

1

constructor

Cons

abs x map f xs abs [-2,3]

thunkthunk

evaluate

case (abs 1) : (map abs [-2, 3]) of

(_:xs) -> xs

map abs [-2, 3]

a result value

4. Evaluation

Page 119: Lazy evaluation illustrated - GitHub Pages · One of the mental models for Haskell program main = exp aa (exp ab exp ac exp ad) exp ac = exp aca exp acb exp ad = exp ada exp adb exp

Examples of evaluations

4. Evaluation

* no optimizing case (without –O)

Page 120: Lazy evaluation illustrated - GitHub Pages · One of the mental models for Haskell program main = exp aa (exp ab exp ac exp ad) exp ac = exp aca exp acb exp ad = exp ada exp adb exp

References : [D5], [D6], [D8], [D9], [D10], [H10]

Example of repeat

repeat 1

1 : repeat 1

1 : 1 : repeat 1

1 : 1 : 1 : repeat 1

4. Evaluation

Page 121: Lazy evaluation illustrated - GitHub Pages · One of the mental models for Haskell program main = exp aa (exp ab exp ac exp ad) exp ac = exp aca exp acb exp ad = exp ada exp adb exp

References : [D5], [D6], [D8], [D9], [D10], [H10]

Example of repeat

repeat 1

1 : repeat 1

Cons 1 (repeat 1)

Cons

1thunk

1repeat

1 : 1 : repeat 1

Cons 1 (Cons 1 (repeat 1) )

1 : 1 : 1 : repeat 1

Cons 1 (Cons 1 (Cons 1 (repeat 1) ) )

Cons

1

Cons

1thunk

1repeat

Cons

1

Cons

1thunk

1repeat

Cons

1

1repeat

1repeat

4. Evaluation

Page 122: Lazy evaluation illustrated - GitHub Pages · One of the mental models for Haskell program main = exp aa (exp ab exp ac exp ad) exp ac = exp aca exp acb exp ad = exp ada exp adb exp

References : [D5], [D6], [D8], [D9], [D10], [H10]

Example of map

map f [1, 2, 3]

f 1 : map f [2, 3]

f 1 : f 2 : map f [3]

f 1 : f 2 : f 3

...

4. Evaluation

Page 123: Lazy evaluation illustrated - GitHub Pages · One of the mental models for Haskell program main = exp aa (exp ab exp ac exp ad) exp ac = exp aca exp acb exp ad = exp ada exp adb exp

References : [D5], [D6], [D8], [D9], [D10], [H10]

Example of map

map f [1, 2, 3]

f 1 : map f [2, 3]

f 1 : f 2 : map f [3]

f 1 : f 2 : f 3

Cons (f 1) (map f [2, 3])

Cons (f 1) (Cons (f 2) (map f [3]) )

Cons (f 1) (Cons (f 2) (Cons (f 3) Nil ) )

Cons Cons Cons Nil

f

1

f

2

f

3

Cons Cons

f

1

f

2

Cons

f

1

......

thunk

map f [2,3]

thunk

map f [3]

4. Evaluation

Page 124: Lazy evaluation illustrated - GitHub Pages · One of the mental models for Haskell program main = exp aa (exp ab exp ac exp ad) exp ac = exp aca exp acb exp ad = exp ada exp adb exp

References : [D5], [D6], [D8], [D9], [D10], [H10]

Example of foldl (non-strict)

foldl (+) (0 + 1) [2 .. 100]

foldl (+) ((0 + 1) + 2) [3 .. 100]

foldl (+) (((0 + 1) + 2) + 3) [4 .. 100]

foldl (+) 0 [1 .. 100]

...

4. Evaluation

Page 125: Lazy evaluation illustrated - GitHub Pages · One of the mental models for Haskell program main = exp aa (exp ab exp ac exp ad) exp ac = exp aca exp acb exp ad = exp ada exp adb exp

References : [D5], [D6], [D8], [D9], [D10], [H10]

Example of foldl (non-strict)

(+)

0 1

(+)

2

(+)

3

thunk1 thunk2 thunk3

(+)

0 1

(+)

2

thunk1 thunk2

(+)

0 1

thunk1foldl (+) (0 + 1) [2 .. 100]

foldl (+) ((0 + 1) + 2) [3 .. 100]

foldl (+) (((0 + 1) + 2) + 3) [4 .. 100]

let thunk1 = (0 + 1)

in foldl (+) thunk1 [2 .. 100]

let thunk2 = (thunk1 + 2)

in foldl (+) thunk2 [3 .. 100]

let thunk3 = (thunk2 + 3)

in foldl (+) thunk3 [4 .. 100]

foldl (+) 0 [1 .. 100]

heap memory

...

*show only accumulation value

4. Evaluation

Page 126: Lazy evaluation illustrated - GitHub Pages · One of the mental models for Haskell program main = exp aa (exp ab exp ac exp ad) exp ac = exp aca exp acb exp ad = exp ada exp adb exp

References : [D5], [D6], [D8], [D9], [D10], [H10]

Example of foldl’ (strict)

foldl’ (+) 0 [1 .. 100]

foldl’ (+) (0 + 1) [2 .. 100]

foldl’ (+) (1 + 2) [3 .. 100]

foldl’ (+) (3 + 3) [4 .. 100]

...

4. Evaluation

Page 127: Lazy evaluation illustrated - GitHub Pages · One of the mental models for Haskell program main = exp aa (exp ab exp ac exp ad) exp ac = exp aca exp acb exp ad = exp ada exp adb exp

References : [D5], [D6], [D8], [D9], [D10], [H10]

Example of foldl’ (strict)

foldl’ (+) 0 [1 .. 100]

let thunk1 = (0 + 1)

in thunk1 `seq`

foldl’ (+) thunk1 [2 .. 100]

foldl’ (+) (0 + 1) [2 .. 100]

let thunk2 = (1 + 2)

in thunk2 `seq`

foldl’ (+) thunk2 [3 .. 100]

foldl’ (+) (1 + 2) [3 .. 100]

let thunk3 = (3 + 3)

in thunk3 `seq`

foldl’ (+) thunk3 [4 .. 100]

foldl’ (+) (3 + 3) [4 .. 100]

(+)

0 1

heap memory

thunk1

I# 1#

(+)

2

thunk2

I# 3#

I# 1#

eval

by seq

(+)

3

thunk3

I# 6#

I# 3#

...

4. Evaluation

Page 128: Lazy evaluation illustrated - GitHub Pages · One of the mental models for Haskell program main = exp aa (exp ab exp ac exp ad) exp ac = exp aca exp acb exp ad = exp ada exp adb exp

References : [D5], [D6], [D8], [D9], [D10], [H10]

Example of foldl (non-strict) and foldl’ (strict)

foldl (+) (0 + 1) [2 .. 100]

foldl (+) ((0 + 1) + 2) [3 .. 100]

foldl (+) (((0 + 1) + 2) + 3) [4 .. 100]

foldl’ (+) (0 + 1) [2 .. 100]

foldl’ (+) (1 + 2) [3 .. 100]

foldl’ (+) (3 + 3) [4 .. 100]

4. Evaluation

Page 129: Lazy evaluation illustrated - GitHub Pages · One of the mental models for Haskell program main = exp aa (exp ab exp ac exp ad) exp ac = exp aca exp acb exp ad = exp ada exp adb exp

(+)

References : [D5], [D6], [D8], [D9], [D10], [H10]

Example of foldl (non-strict) and foldl’ (strict)

0 1 2

(+)

3

heap memory

(+)

(+)

0 1 2

(+)

0 1

(+)

3

(+)

I# 3#

I# 6#

2

(+)

I# 1#

1

(+)

0

I# 3#

I# 1#

foldl (+) (0 + 1) [2 .. 100]

foldl (+) ((0 + 1) + 2) [3 .. 100]

foldl (+) (((0 + 1) + 2) + 3) [4 .. 100]

foldl’ (+) (0 + 1) [2 .. 100]

foldl’ (+) (1 + 2) [3 .. 100]

foldl’ (+) (3 + 3) [4 .. 100]

4. Evaluation

Page 130: Lazy evaluation illustrated - GitHub Pages · One of the mental models for Haskell program main = exp aa (exp ab exp ac exp ad) exp ac = exp aca exp acb exp ad = exp ada exp adb exp

Controlling the evaluation

4. Evaluation

Page 131: Lazy evaluation illustrated - GitHub Pages · One of the mental models for Haskell program main = exp aa (exp ab exp ac exp ad) exp ac = exp aca exp acb exp ad = exp ada exp adb exp

How to drive the evaluation

An expression

driving the evaluation by

and deconstructing by

pattern-

matching

primitive

operation

forcing

function

special

syntax

special

pragma

case expression

function definition

+, *, ... seq

$!

pseq

deepseq

force

$!!

rnf

,...

! Strict

StrictData

* ghc 8.0 ~

compile

option

-O

-fstrictness

-XStrict

-XStrictData* ghc 8.0 ~

strict

function

foldl’

scanl’

,...

4. Evaluation

Page 132: Lazy evaluation illustrated - GitHub Pages · One of the mental models for Haskell program main = exp aa (exp ab exp ac exp ad) exp ac = exp aca exp acb exp ad = exp ada exp adb exp

References : [H1] Ch.3, [D2], [D1], [H5], [W1]

(1) Evaluation by pattern-matching

case ds of

x:xs -> f x xs

[] -> False

pattern-matching in case expression

f Just _ = True

f Nothing = False

pattern-matching in function definition

forcing

(drive the evaluation of the thunk)

forcing

(drive the evaluation of the thunk)

4. Evaluation

Page 133: Lazy evaluation illustrated - GitHub Pages · One of the mental models for Haskell program main = exp aa (exp ab exp ac exp ad) exp ac = exp aca exp acb exp ad = exp ada exp adb exp

References : [H1] Ch.3, [D2], [D1], [H5], [W1], [H8] Ch.4

(1) Evaluation by pattern-matching

Strict patterns drive the evaluation Lazy patterns postpone the evaluation.

function definition

let binding patterncase expression

irrefutable patterns

case ds of

x:xs -> f x xs

[] -> False

f Just _ = True

f Nothing = False

let (x:xs) = fun args

f ~(Just _ ) = True

f ~(Nothing) = False

There are two kinds of pattern-matching.

[H1] 3.17

4. Evaluation

Page 134: Lazy evaluation illustrated - GitHub Pages · One of the mental models for Haskell program main = exp aa (exp ab exp ac exp ad) exp ac = exp aca exp acb exp ad = exp ada exp adb exp

References : [D3], [H5], [H12]

(2) Evaluation by primitive operation

f x y = x + y

primitive (built-in) operationforcing x and y

(drive the evaluation of the thunks)

+, *, ...

(+) (I# a) (I# b) = I# (a+b)

pattern-matching

primitive operations are defined such as

4. Evaluation

* pseudo code

Page 135: Lazy evaluation illustrated - GitHub Pages · One of the mental models for Haskell program main = exp aa (exp ab exp ac exp ad) exp ac = exp aca exp acb exp ad = exp ada exp adb exp

References : [B4] Ch.25, [D9], [B6] Ch.7, [B2], [S1], [S2]

(3) Evaluation by strict version function

foldl’ (+) 0 xs

strict version functionstrict application of the operator

4. Evaluation

scanl’ (+) 0 xs

::

Page 136: Lazy evaluation illustrated - GitHub Pages · One of the mental models for Haskell program main = exp aa (exp ab exp ac exp ad) exp ac = exp aca exp acb exp ad = exp ada exp adb exp

References : [B5] Ch.2, [B4] Ch.24, 25, [B6] Ch.7, [H1] Ch.6, [D2], [B2], [D1], [D2]. [S1], [S2]

(4) Evaluation by forcing function

seq x y

forcing functions to WHNFforcing

(drive the evaluation of the thunk)

forcing functions to NF

f $! x

pseq x y

deepseq x y

f $!! x

force x

rnf x

4. Evaluation

Page 137: Lazy evaluation illustrated - GitHub Pages · One of the mental models for Haskell program main = exp aa (exp ab exp ac exp ad) exp ac = exp aca exp acb exp ad = exp ada exp adb exp

References : [B5] Ch.2, [B4] Ch.24, 25, [H1] Ch.6, [D2], [B2], [D1], [D2]. [S1], [S2]

(4) Evaluation by forcing function

WHNF

NF

an expression

WHNF

NF

an expression

evaluateseq

$!

pseq

deepseq

force

$!!

rnf

to WHNF to NF

4. Evaluation

evaluate

Page 138: Lazy evaluation illustrated - GitHub Pages · One of the mental models for Haskell program main = exp aa (exp ab exp ac exp ad) exp ac = exp aca exp acb exp ad = exp ada exp adb exp

References : [B5] Ch.2, [B4] Ch.24, 25, [H1] Ch.6, [D2], [B2], [D1], [D2]. [S1], [S2]

(4) Evaluation by forcing function

to WHNF to NF

force

rnf

deepseq

$!!

seq

$!

pseq

two arguments

function application

one argument

sequential order

basic operation

4. Evaluation

Page 139: Lazy evaluation illustrated - GitHub Pages · One of the mental models for Haskell program main = exp aa (exp ab exp ac exp ad) exp ac = exp aca exp acb exp ad = exp ada exp adb exp

References : [B5] Ch.2, [B4] Ch.24, 25, [H1] Ch.6, [D2], [B2], [D1], [D2]. [S1], [S2]

(4) Evaluation by forcing function

to WHNF to NF

force

rnf

deepseq

$!!

seq

$!

pseq

two expressions

function application

one expression

sequential order

basic operation

deepseq a b = rnf a `seq` b

force x = x `deepseq` x

f $!! x = x `deepseq` f x

built-in

f $! x = let !vx = x in f vx

pseq x y = x `seq` lazy yclass NFData a where

rnf :: a -> ()

instance NFData Int where rnf !_ = ():

instance NFData a => NFData [a] wherernf [] = ()rnf (x:xs) = rnf x `seq` rnf xs

definition

4. Evaluation

Page 140: Lazy evaluation illustrated - GitHub Pages · One of the mental models for Haskell program main = exp aa (exp ab exp ac exp ad) exp ac = exp aca exp acb exp ad = exp ada exp adb exp

References : [B5] Ch.2, [B4] Ch.24, 25, [H1] Ch.6, [D2], [B2], [D1], [D10]. [S1], [S2]

(4) Evaluation by forcing function

seq a ()

deepseq a ()

length a

a = map abs [1, -2, 3, -4]

Cons Cons Cons

1 2 3

thunk

1abs x

Cons Nil

Cons Cons Cons Cons Nil

4

thunk

-2abs x

thunk

3abs x

thunk

-4abs x

thunk

1abs x

Cons

absmap f xs [-2, 3, -4]

thunk

4. Evaluation

full evaluation

evaluate spine only

evaluate head only

Page 141: Lazy evaluation illustrated - GitHub Pages · One of the mental models for Haskell program main = exp aa (exp ab exp ac exp ad) exp ac = exp aca exp acb exp ad = exp ada exp adb exp

References : [D1], [H2] Ch.7, [H1] Ch.4, [B4] Ch.25, [B2] Ch.7, [W6], [H4] Ch.22, [W4]

(5) Evaluation by special syntax

{-# LANGUAGE BangPatterns #-}

f !xs = g xs

Bang pattern

data Pair = Pair !a !b

[H2] 7.19

Strictness flag

Strictness annotation

[H1] 4.2.1

Strictness annotations assist strictness analysis.

4. Evaluation

arguments are evaluated

before function application

arguments are evaluated

before constructor application

Page 142: Lazy evaluation illustrated - GitHub Pages · One of the mental models for Haskell program main = exp aa (exp ab exp ac exp ad) exp ac = exp aca exp acb exp ad = exp ada exp adb exp

References : [H13]

(6) Evaluation by special pragma

{-# LANGUAGE Strict #-}

let f xs = g xs in f ys

data Pair = Pair a b

Strict pragma

{-# LANGUAGE StrictData #-}

data Pair = Pair a b

Strict and StrictData pragmas are module level control.

These can use in ghc 8.0 or later.

* ghc 8.0 ~

4. Evaluation

Special pragma for strictness language extension

StrictData pragma * ghc 8.0 ~

arguments are evaluated

before application

Page 143: Lazy evaluation illustrated - GitHub Pages · One of the mental models for Haskell program main = exp aa (exp ab exp ac exp ad) exp ac = exp aca exp acb exp ad = exp ada exp adb exp

References : [H2], [H13]

(7) Evaluation by compile option

strictness analysis

$ ghc -O

$ ghc -fstrictness

$ ghc -XStrict

$ ghc -XStrictData

strictness language extension * ghc 8.0 ~

4. Evaluation

apply Strict pragma

apply StrictData pragma

Turn on strictness analysis.

Implied by “-O”.

Compile option

Turn on optimization.

Imply “-fstrictness”.

Page 144: Lazy evaluation illustrated - GitHub Pages · One of the mental models for Haskell program main = exp aa (exp ab exp ac exp ad) exp ac = exp aca exp acb exp ad = exp ada exp adb exp

5. Implementation of evaluator

Page 145: Lazy evaluation illustrated - GitHub Pages · One of the mental models for Haskell program main = exp aa (exp ab exp ac exp ad) exp ac = exp aca exp acb exp ad = exp ada exp adb exp

Lazy graph reduction

5. Implementation of evaluator

Page 146: Lazy evaluation illustrated - GitHub Pages · One of the mental models for Haskell program main = exp aa (exp ab exp ac exp ad) exp ac = exp aca exp acb exp ad = exp ada exp adb exp

References : [D3], [D2], [D5], [W5], [H4] Ch.12, [B8] Ch.3

Tree

An expression can be represented in the form of Abstract Syntax Tree (AST).

AST is reduced using stack (sequential access memory).

5. Implementation of evaluator

exp

exp exp

expexp exp

expexp exp

Page 147: Lazy evaluation illustrated - GitHub Pages · One of the mental models for Haskell program main = exp aa (exp ab exp ac exp ad) exp ac = exp aca exp acb exp ad = exp ada exp adb exp

References : [D3], [D2], [D5], [W5], [H4] Ch.12, [B8] Ch.3

Graph

exp

exp exp

exp

An expression can be also represented in the form of Graph.

Graph can share subexpressions to evaluate at once.

So, graph is reduced using heap (random access memory) rather than stack.

5. Implementation of evaluator

exp

expexp exp

shared term

exp

Page 148: Lazy evaluation illustrated - GitHub Pages · One of the mental models for Haskell program main = exp aa (exp ab exp ac exp ad) exp ac = exp aca exp acb exp ad = exp ada exp adb exp

References : [D3], [W5], [H4] Ch.11, 12, [B8] Ch.3

Graph can be reduced in some order

square (1+2)

5. Implementation of evaluator

square 1 + 2

+ 1 2

square (1+2)

square 3

+ 1 2

(1+2) * (1+2)

1 + 2

+ 1 2

3 *

top-level redex

inner level redexwhich first ?

reduce top-level (outermost) firstreduce inner level first

for call-by-value for call-by-need

To select top-level redex first, the evaluation of arguments can be postponed.

Page 149: Lazy evaluation illustrated - GitHub Pages · One of the mental models for Haskell program main = exp aa (exp ab exp ac exp ad) exp ac = exp aca exp acb exp ad = exp ada exp adb exp

References : [D3], [D2], [D5], [W5], [H4] Ch.11, 12, [B8] Ch.3

Normal order reduction is implemented by lazy graph reduction

exp

exp exp

exp expexp

Normal order (leftmost outermost) reduction is implemented by lazy graph reduction

to select top-level redex first.

5. Implementation of evaluator

exp exp

find top-level redex

and reduce it

exp exp exp exp...

an expression

Normal order (leftmost outermost) first

Given an application of a function, the outermost redex is the function application itself.

Normal order reduction Lazy graph reduction

implemented by

Page 150: Lazy evaluation illustrated - GitHub Pages · One of the mental models for Haskell program main = exp aa (exp ab exp ac exp ad) exp ac = exp aca exp acb exp ad = exp ada exp adb exp

STG-machine

5. Implementation of evaluator

Page 151: Lazy evaluation illustrated - GitHub Pages · One of the mental models for Haskell program main = exp aa (exp ab exp ac exp ad) exp ac = exp aca exp acb exp ad = exp ada exp adb exp

References : [H5], [H6], [H7], [D15]

Abstract machine

Graph(expression)

STG-machineEvaluator(abstract machine)

GHC uses abstract machine to reduce the expression.

It’s called “STG-machine”.

5. Implementation of evaluator

evaluate

(reduce / execute)

Page 152: Lazy evaluation illustrated - GitHub Pages · One of the mental models for Haskell program main = exp aa (exp ab exp ac exp ad) exp ac = exp aca exp acb exp ad = exp ada exp adb exp

References : [H5], [H6], [H7], [D15]

Concept layer

Haskell code take 5 [1..10]

:

Graph

(internal representation

of the expression)

Evaluator (reducer, executer)

(abstract machine)

STG Registers Stack Heap

R1, ...

STG-machine

5. Implementation of evaluator

Page 153: Lazy evaluation illustrated - GitHub Pages · One of the mental models for Haskell program main = exp aa (exp ab exp ac exp ad) exp ac = exp aca exp acb exp ad = exp ada exp adb exp

References : [H5], [H6], [H7], [D15]

STG-machine

STG-machine is abstraction machine

which is defined by operational semantics.

STG-machine efficiently performs lazy graph reduction.

STG Registers Stack Heap

R1, ...

STG-machine

Static

5. Implementation of evaluator

Page 154: Lazy evaluation illustrated - GitHub Pages · One of the mental models for Haskell program main = exp aa (exp ab exp ac exp ad) exp ac = exp aca exp acb exp ad = exp ada exp adb exp

References : [H5], [H6], [H7], [D15]

STG-machine

STG Registers Stack Heap

R1, ...

STG-machine

mainly used for

nest continuation

argument passing

mainly used for

allocating objects

(thunks, datas,

functions)

Static

mainly used for

call/return convention

various control

mainly used for

code

static objects

5. Implementation of evaluator

Page 155: Lazy evaluation illustrated - GitHub Pages · One of the mental models for Haskell program main = exp aa (exp ab exp ac exp ad) exp ac = exp aca exp acb exp ad = exp ada exp adb exp

References : [H5], [H10]

Example of mapping a code to a graph

main

print head [1..]

head [1..]

main = print (head [1..])

5. Implementation of evaluator

Page 156: Lazy evaluation illustrated - GitHub Pages · One of the mental models for Haskell program main = exp aa (exp ab exp ac exp ad) exp ac = exp aca exp acb exp ad = exp ada exp adb exp

References : [H5], [H10]

Example of mapping a code to a graph

main

print head [1..]

head [1..]

main = print (head [1..])

5. Implementation of evaluator

Page 157: Lazy evaluation illustrated - GitHub Pages · One of the mental models for Haskell program main = exp aa (exp ab exp ac exp ad) exp ac = exp aca exp acb exp ad = exp ada exp adb exp

References : [H5], [H10]

Example of mapping a code to a graph

code

code code

code code

main = print (head [1..])

main

print head [1..]

head[1..]

function

function thunk

function thunk

build

build

5. Implementation of evaluator

Page 158: Lazy evaluation illustrated - GitHub Pages · One of the mental models for Haskell program main = exp aa (exp ab exp ac exp ad) exp ac = exp aca exp acb exp ad = exp ada exp adb exp

References : [H5], [H6], [H7], [D15]

Self-updating model

expression code free variables

info ptr

a thunk

update code

info ptr

a data value

data componentsconstructor

evaluate and update

(replace myself to result value)

5. Implementation of evaluator

GHC’s internal representationExpression

Page 159: Lazy evaluation illustrated - GitHub Pages · One of the mental models for Haskell program main = exp aa (exp ab exp ac exp ad) exp ac = exp aca exp acb exp ad = exp ada exp adb exp

References : [H5], [H6], [H4] Ch.12, [D15]

Unreferenced expressions (objects) will be removed by GC5. Implementation of evaluator

a thunk

code

an evaluated expression

unreferenced

objects

collected by GC(Garbage Collection)

evaluate and updateevaluate and update

GHC’s internal representationExpression

collected by GC(Garbage Collection)

Page 160: Lazy evaluation illustrated - GitHub Pages · One of the mental models for Haskell program main = exp aa (exp ab exp ac exp ad) exp ac = exp aca exp acb exp ad = exp ada exp adb exp

References : [H5], [H6], [H4] Ch.3

STG-machine associates directly ...

STG-machine associates directly lambda calculus and physical machine.

5. Implementation of evaluator

( λx . body ) arg

let x = arg

in body

case arg of

x -> body

x

x

a thunk

an evaluated value

heap memory

lazy

(non-strict)

eager

(strict)

arg

built a thunk

evaluate the arg

bind with a lazy expression

bind with an evaluated expression

arg

Page 161: Lazy evaluation illustrated - GitHub Pages · One of the mental models for Haskell program main = exp aa (exp ab exp ac exp ad) exp ac = exp aca exp acb exp ad = exp ada exp adb exp

The STG-machine is ...

The STG-machine is the marriage of Lambda calculus and Turing machine.

5. Implementation of evaluator

λλλ λ

λλ λ

STG-machine

Lambda calculus Turing machine

Page 162: Lazy evaluation illustrated - GitHub Pages · One of the mental models for Haskell program main = exp aa (exp ab exp ac exp ad) exp ac = exp aca exp acb exp ad = exp ada exp adb exp

References : [H5], [H6], [H7], [D15]

STG-dump shows which expression is built as thunks5. Implementation of evaluator

module Example where

fun f1 n = take 1 (f1 n)

[Example.hs]

Example.fun

:: forall a_aME t_aMF. (t_aMF -> [a_aME]) -> t_aMF ->

[a_aME]

[GblId,

Arity=2,

Caf=NoCafRefs,

Str=DmdType <L,1*C1(U)><L,U>,

Unf=OtherCon []] =

﹨r srt:SRT:[] [f1_sQT n_sQU]

let {

sat_sQV [Occ=Once, Dmd=<L,1*U>] :: [a_aMH]

[LclId, Str=DmdType] =

﹨s srt:SRT:[] [] f1_sQT n_sQU;

} in GHC.List.take_unsafe_UInt 1 sat_sQV;

STG code dump

by “$ ghc -O -ddump-stg Example.hs”

thunk

f1_sQT n_sQUf1_sQT n_sQU

heap memory

build/allocate

let expression in STG language

Page 163: Lazy evaluation illustrated - GitHub Pages · One of the mental models for Haskell program main = exp aa (exp ab exp ac exp ad) exp ac = exp aca exp acb exp ad = exp ada exp adb exp

6. Semantics

Page 164: Lazy evaluation illustrated - GitHub Pages · One of the mental models for Haskell program main = exp aa (exp ab exp ac exp ad) exp ac = exp aca exp acb exp ad = exp ada exp adb exp

Bottom

6. Semantics

Page 165: Lazy evaluation illustrated - GitHub Pages · One of the mental models for Haskell program main = exp aa (exp ab exp ac exp ad) exp ac = exp aca exp acb exp ad = exp ada exp adb exp

References : [B2] Ch.2, [W4]

A well formed expression should have a value

evaluate

A value

1 + 2

An expression

3

6. Semantics

Page 166: Lazy evaluation illustrated - GitHub Pages · One of the mental models for Haskell program main = exp aa (exp ab exp ac exp ad) exp ac = exp aca exp acb exp ad = exp ada exp adb exp

?

References : [B2] Ch.2, [H1] Ch.3, [W4], [H4] Ch.2, 22

What is a value in this case?

evaluate

A value ?

An expression

infinite loop or

partial function

a non-terminating expression

6. Semantics

Page 167: Lazy evaluation illustrated - GitHub Pages · One of the mental models for Haskell program main = exp aa (exp ab exp ac exp ad) exp ac = exp aca exp acb exp ad = exp ada exp adb exp

References : [B2] Ch.2, [H1] Ch.3, [W4], [H4] Ch.2, 22

A value “bottom” is introduced

evaluate

A value

An expression

bottom

a non-terminating expression

6. Semantics

infinite loop or

partial function

Page 168: Lazy evaluation illustrated - GitHub Pages · One of the mental models for Haskell program main = exp aa (exp ab exp ac exp ad) exp ac = exp aca exp acb exp ad = exp ada exp adb exp

References : [B2] Ch.2, 9, [H1] Ch.3, [W4], [H4] Ch.2, 22

Bottom

A value

Bottom (⊥) is “an undefined value”.

Bottom (⊥) is “a non-terminating value”.

6. Semantics

Page 169: Lazy evaluation illustrated - GitHub Pages · One of the mental models for Haskell program main = exp aa (exp ab exp ac exp ad) exp ac = exp aca exp acb exp ad = exp ada exp adb exp

References : [B2] Ch.2, 9, [H1] Ch.3, [W4], [H4] Ch.2, 22

“undefined” function represents “bottom” in GHC

Haskell code GHC’s internal representation

undefined :: a ⊥

Expression

info ptr

code

6. Semantics

GHC.Err.undefined

Page 170: Lazy evaluation illustrated - GitHub Pages · One of the mental models for Haskell program main = exp aa (exp ab exp ac exp ad) exp ac = exp aca exp acb exp ad = exp ada exp adb exp

Strict/Non-strict

6. Semantics

Page 171: Lazy evaluation illustrated - GitHub Pages · One of the mental models for Haskell program main = exp aa (exp ab exp ac exp ad) exp ac = exp aca exp acb exp ad = exp ada exp adb exp

an expression

References : [B2] Ch.2, [W1], [W4], [H4] Ch.2, 22, [H15], [H16]

Strictness6. Semantics

definitely evaluated?

Strictness is “evaluation demand” of the expression.

Page 172: Lazy evaluation illustrated - GitHub Pages · One of the mental models for Haskell program main = exp aa (exp ab exp ac exp ad) exp ac = exp aca exp acb exp ad = exp ada exp adb exp

an expression

References : [B2] Ch.2, [W1], [W4], [H4] Ch.2, 22, [H15], [H16]

Strict and non-strict6. Semantics

“Strict” means that

the expression is definitely evaluated.

“Non-strict” means that

the expression may or may not be evaluated.

Page 173: Lazy evaluation illustrated - GitHub Pages · One of the mental models for Haskell program main = exp aa (exp ab exp ac exp ad) exp ac = exp aca exp acb exp ad = exp ada exp adb exp

an expression

References : [B2] Ch.2, [W1], [W4], [H4] Ch.2, 22, [H15], [H16]

Strict and non-strict6. Semantics

“Strict” means that

the expression is definitely evaluated.

“Non-strict” means that

the expression may or may not be evaluated.

GHC implements non-strict semantics by lazy evaluation.

Page 174: Lazy evaluation illustrated - GitHub Pages · One of the mental models for Haskell program main = exp aa (exp ab exp ac exp ad) exp ac = exp aca exp acb exp ad = exp ada exp adb exp

References : [H15], [H16], [B2] Ch.2, [W1], [W4], [H4] Ch.2, 22

GHC has the lattice of strictness6. Semantics

an expression

WHNF or ⊥

NF

WHNF or ⊥

NF

an expression

NF or ⊥

an expressionan expression

a lazy demand

a head-strict demand

a hyperstrict demand

a structured strictness demand

StrictNon-strict

There are multiple levels in strict.

Page 175: Lazy evaluation illustrated - GitHub Pages · One of the mental models for Haskell program main = exp aa (exp ab exp ac exp ad) exp ac = exp aca exp acb exp ad = exp ada exp adb exp

References : [H15], [H16], [B2] Ch.2, [W1], [W4], [H4] Ch.2, 22

Strictness of a function6. Semantics

A function places “strictness demands” on each of its arguments.

function

argument 2

argument 1 evaluated ?

evaluated ?

Will arguments be definitely evaluated in the function?

Page 176: Lazy evaluation illustrated - GitHub Pages · One of the mental models for Haskell program main = exp aa (exp ab exp ac exp ad) exp ac = exp aca exp acb exp ad = exp ada exp adb exp

References : [B2] Ch.2, [W1], [W4], [H4] Ch.2, 22

Strictness of a function is formally defined6. Semantics

Strictness of a function can be defined with the association between input and output.

“given a non-terminating arguments, the function will terminate?”

⊥ f

function

input output?

f ⊥ = ?

definition

Page 177: Lazy evaluation illustrated - GitHub Pages · One of the mental models for Haskell program main = exp aa (exp ab exp ac exp ad) exp ac = exp aca exp acb exp ad = exp ada exp adb exp

References : [B2] Ch.2, [W1], [W4], [H4] Ch.2, 22

Definition of the strict function

⊥ f ⊥

Strict function

input output

Strict function’s output is bottom when input is bottom.

f ⊥ = ⊥

given a non-terminating arguments, strict function will not terminate.

6. Semantics

definition

Page 178: Lazy evaluation illustrated - GitHub Pages · One of the mental models for Haskell program main = exp aa (exp ab exp ac exp ad) exp ac = exp aca exp acb exp ad = exp ada exp adb exp

Non-strict function’s output is not bottom when input is bottom.

References : [B2] Ch.2, [W1], [W4], [H4] Ch.2, 22

Definition of the non-strict function

⊥ f ≠ ⊥

Non-strict function

input outputan evaluated value or

an unevaluated expression

given a non-terminating arguments, non-strict function will terminate.

6. Semantics

f ⊥ ≠⊥

definition

Page 179: Lazy evaluation illustrated - GitHub Pages · One of the mental models for Haskell program main = exp aa (exp ab exp ac exp ad) exp ac = exp aca exp acb exp ad = exp ada exp adb exp

⊥ f ⊥

Strict function

input output

Strict

⊥ f ≠ ⊥

an evaluated value or

an unevaluated expression

Non-strict function

input output

Non-strict

References : [B2] Ch.2, [W1], [W4], [H4] Ch.2, 22

Strict and Non-strict functions6. Semantics

Page 180: Lazy evaluation illustrated - GitHub Pages · One of the mental models for Haskell program main = exp aa (exp ab exp ac exp ad) exp ac = exp aca exp acb exp ad = exp ada exp adb exp

f

Strict functionStrict

evaluate

the argument

to WHNF passing

the evaluated

argument

an argument

no need to evaluate the argument

f

Non-strict function

Non-strict

build a thunkpassing

the thunk

an argument

evaluate the argument if needed

References : [B2] Ch.2, [W1], [W4], [H4] Ch.2, 22

Function application and strictness6. Semantics

Postpone or Prepay

The front stage is also important.

Page 181: Lazy evaluation illustrated - GitHub Pages · One of the mental models for Haskell program main = exp aa (exp ab exp ac exp ad) exp ac = exp aca exp acb exp ad = exp ada exp adb exp

f $!! argf $! argStrict

(deepseq)(seq)

References : [B2] Ch.2, [W1], [W4], [H4] Ch.2, 22

Strict and normal form

to WHNF to NF

6. Semantics

Strict ≠ Normal form

Example of function application

Non-strict f $ arg

Page 182: Lazy evaluation illustrated - GitHub Pages · One of the mental models for Haskell program main = exp aa (exp ab exp ac exp ad) exp ac = exp aca exp acb exp ad = exp ada exp adb exp

Lifted and boxed types

6. Semantics

Page 183: Lazy evaluation illustrated - GitHub Pages · One of the mental models for Haskell program main = exp aa (exp ab exp ac exp ad) exp ac = exp aca exp acb exp ad = exp ada exp adb exp

References : [W4], [B2], [H14]

Lifted types6. Semantics

Lifted types include bottom as an element.

0 1

Lifted type

2 ...

lifted⊥

Page 184: Lazy evaluation illustrated - GitHub Pages · One of the mental models for Haskell program main = exp aa (exp ab exp ac exp ad) exp ac = exp aca exp acb exp ad = exp ada exp adb exp

References : [W4], [B2], [H14]

Lifted type’s declaration implicitly include bottom6. Semantics

False True

0 1

Bool type

Int type

2 ...

data Bool = False

| True

| ⊥

data Int = I# Int#

| ⊥

implicitly included

implicitly included

data declaration

Page 185: Lazy evaluation illustrated - GitHub Pages · One of the mental models for Haskell program main = exp aa (exp ab exp ac exp ad) exp ac = exp aca exp acb exp ad = exp ada exp adb exp

References : [W4], [B2], [H14]

Lifted type are also implemented by uniform representation6. Semantics

Nothing

I# 0#

Just

data Maybe a = Nothing

| Just a

| ⊥

data Int = I# Int#

| ⊥

data declaration GHC’s internal representation

x :: Maybe a

x :: Int

undefined

code

I# 1#

:

a

undefined

code

Page 186: Lazy evaluation illustrated - GitHub Pages · One of the mental models for Haskell program main = exp aa (exp ab exp ac exp ad) exp ac = exp aca exp acb exp ad = exp ada exp adb exp

References : [W4], [B2], [H14]

Lifted and unlifted types6. Semantics

0 1

Lifted types

2 ...

lifted0# 1#

Unlifted types

2# ...

Lifted types include bottom. Unlifted types do not include bottom.

Int type Int# type

(Bool, Int, Char, Maybe, List, ...) (Int#, Char#, Addr#, Array#, ByteArray#, ...)

Page 187: Lazy evaluation illustrated - GitHub Pages · One of the mental models for Haskell program main = exp aa (exp ab exp ac exp ad) exp ac = exp aca exp acb exp ad = exp ada exp adb exp

References : [W4], [B2], [H14]

Example of lifted and unlifted types6. Semantics

Lifted types Unlifted types

data1

x :: Array#

Nothing

Just

x :: Just a

code

data2

data3

I# 0#

x :: Int

code

I# 1#

:

#7

x :: Int#

no bottom

no bottom

a

Page 188: Lazy evaluation illustrated - GitHub Pages · One of the mental models for Haskell program main = exp aa (exp ab exp ac exp ad) exp ac = exp aca exp acb exp ad = exp ada exp adb exp

References : [W4], [B2], [H14]

Boxed and unboxed types6. Semantics

value

value

Boxed

types

Unboxed

types

pointed

Boxed types are represented as a pointer.

Unboxed types are represented other than a pointer.

- no bottom (can’t be lifted)

- no thunk (can’t be postponed)

- no polymorphism (non-uniform size)

+ low cost memory size (no pointer)

+ high performance (no wrap/unwrap)

Page 189: Lazy evaluation illustrated - GitHub Pages · One of the mental models for Haskell program main = exp aa (exp ab exp ac exp ad) exp ac = exp aca exp acb exp ad = exp ada exp adb exp

References : [W4], [B2], [H14]

Example of boxed and unboxed types6. Semantics

I# 0#

x :: Int

I# 1#

:

#7

x :: Int#

no bottom

Boxed

types

Unboxed

types

data1

x :: Array#

data2

data3

Page 190: Lazy evaluation illustrated - GitHub Pages · One of the mental models for Haskell program main = exp aa (exp ab exp ac exp ad) exp ac = exp aca exp acb exp ad = exp ada exp adb exp

References : [W4], [B2], [H14]

Lifted and boxed types6. Semantics

Lifted types Unlifted types

Boxed

types

Unboxed

types

Int

Char

Float

Maybe

:

Array#

ByteArray#

:

Int#

Char#

Float#

:

no bottom

no bottom

no packed

unboxed can’t be lifted

Page 191: Lazy evaluation illustrated - GitHub Pages · One of the mental models for Haskell program main = exp aa (exp ab exp ac exp ad) exp ac = exp aca exp acb exp ad = exp ada exp adb exp

References : [W4], [B2], [H14]

Example of lifted and boxed types6. Semantics

Lifted types Unlifted types

Boxed

types

Unboxed

types

I# 0#

x :: Int

code

I# 1#

:

data1

x :: Array#

data2

data3

#7

x :: Int#

include bottom

pointed

Page 192: Lazy evaluation illustrated - GitHub Pages · One of the mental models for Haskell program main = exp aa (exp ab exp ac exp ad) exp ac = exp aca exp acb exp ad = exp ada exp adb exp

References : [B6] Ch.29, [W4], [B2], [H14]

Types and kinds6. Semantics

Lifted types Unlifted types

Boxed

types

Unboxed

types

Int

Char

Float

Maybe

:

Array#

ByteArray#

:

Int#

Char#

Float#

:

kind ‘*’ kind ‘#’

Identifier’s ‘#’ customarily means “primitive” rather than “unboxed” or “unlifted”.

Kind’s ‘#’ means “unlifted”.

Note:

Page 193: Lazy evaluation illustrated - GitHub Pages · One of the mental models for Haskell program main = exp aa (exp ab exp ac exp ad) exp ac = exp aca exp acb exp ad = exp ada exp adb exp

Strictness analysis

6. Semantics

Page 194: Lazy evaluation illustrated - GitHub Pages · One of the mental models for Haskell program main = exp aa (exp ab exp ac exp ad) exp ac = exp aca exp acb exp ad = exp ada exp adb exp

References : [H4] Ch.22, [H8], [W6], [W3], [H15], [H16], [H13], [H2]

Strictness analysis6. Semantics

arguments evaluated ?

function

Strictness analysis analyzes whether a function is sure to evaluate its argument.

analyzed by strictness analyser

Page 195: Lazy evaluation illustrated - GitHub Pages · One of the mental models for Haskell program main = exp aa (exp ab exp ac exp ad) exp ac = exp aca exp acb exp ad = exp ada exp adb exp

arguments evaluated ?

function

References : [H15], [H16], [H2], [H4] Ch.22, [H8], [W6], [W3], [H13]

Strictness analysis in GHC6. Semantics

a lazy demand

a head-strict demand

a hyperstrict demand

a structured strictness demand

a used demand

a head-used demand

unused (absence)

a structured used demand

Strictness demands Absence/usage demands

GHC’s demand analyser implements strictness analysis.

Demand analysis ( = Strictness analysis + Absence analysis + ... )

demand analyser

Page 196: Lazy evaluation illustrated - GitHub Pages · One of the mental models for Haskell program main = exp aa (exp ab exp ac exp ad) exp ac = exp aca exp acb exp ad = exp ada exp adb exp

References : [H15], [H16], [H2], [H4] Ch.22, [H8], [W6], [W3], [H13]

Example of strictness analysis information in GHC6. Semantics

module Example where

f1 :: Bool -> Int -> Maybe Int

f1 c n = case c of

True -> Just n

False -> Nothing

[Example.hs]

==================== Strictness signatures ====================

Example.f1: <S,1*U><L,U>

Strictness analysis dump

by “$ ghc -O -ddump-strsigs Example.hs”

L -- second argument is “Lazy”

S -- first argument is “head-Strict”

GHC shows strictness analysis information with “-ddump-strsigs” and “-ddump-stranal”.

Page 197: Lazy evaluation illustrated - GitHub Pages · One of the mental models for Haskell program main = exp aa (exp ab exp ac exp ad) exp ac = exp aca exp acb exp ad = exp ada exp adb exp

References : [H4] Ch.22, [H8], [W6], [W3], [H15], [H17], [H13]

(1) Strictness analysis are used to avoid the thunk

If GHC knows that a function is strict, arguments is evaluated before application.

GHC finds strict functions by “strictness analysis (demand analysis)”.

heap memory

exp

non-strict function

thunkbuild

non-strict function exp

apply

heap memory

exp

thunkbuild

strict function exp

apply

strict function

6. Semantics

no build

no force

no update

no GC

Page 198: Lazy evaluation illustrated - GitHub Pages · One of the mental models for Haskell program main = exp aa (exp ab exp ac exp ad) exp ac = exp aca exp acb exp ad = exp ada exp adb exp

non-strict

strict

References : [H8], [H4] Ch.22, [W6], [W3], [H15], [H17], [H13]

(1) Strictness analysis are used to avoid the thunk6. Semantics

let x = arg

in body

case arg of

x -> body

let-to-case transformation

heap memory

arg

thunkbuild

heap memory

arg

thunk

build

If GHC knows that a function is strict, GHC performs let-to-case transformation.

Page 199: Lazy evaluation illustrated - GitHub Pages · One of the mental models for Haskell program main = exp aa (exp ab exp ac exp ad) exp ac = exp aca exp acb exp ad = exp ada exp adb exp

References : [H4] Ch.22, [H8], [W6], [W3], [H15], [H17], [H13]

(2) Strictness analysis are also used to optimize6. Semantics

Strict function

evaluate

the argument

evaluated

argumentan argument

evaluate

the argument

evaluated

argumentan argument

f

evaluated (no thunk)

unlifted (no bottom)

if ⊥

if ≠ ⊥

or

a result

optimizing

f

f’

Strictness function can be optimized to assume no thunk, no bottom.

optimized version

Page 200: Lazy evaluation illustrated - GitHub Pages · One of the mental models for Haskell program main = exp aa (exp ab exp ac exp ad) exp ac = exp aca exp acb exp ad = exp ada exp adb exp

References : [H4] Ch.22, [H8], [W6], [W3], [H15], [H17], [H13]

(2) Strictness analysis are also used to optimize6. Semantics

Strict function

evaluate

the argument

evaluated

argumentan argument

evaluate

the argument

evaluated

argumentan argument

f

evaluated (no thunk)

unlifted (no bottom)

if ⊥

if ≠ ⊥

or

a result

optimizing

evaluate

the argument

evaluated

argumentan argument

wf (worker)

evaluated (no thunk)

unlifted (no bottom)

unboxed (no packed)

if ⊥

if ≠ ⊥

or

a resultunpack pack

lightly inlinable

high efficiency

f

f’

optimizing

f (wrapper)

Strictness function can be optimized to assume no thunk, no bottom, no packed.

Page 201: Lazy evaluation illustrated - GitHub Pages · One of the mental models for Haskell program main = exp aa (exp ab exp ac exp ad) exp ac = exp aca exp acb exp ad = exp ada exp adb exp

Sequential order

6. Semantics

Page 202: Lazy evaluation illustrated - GitHub Pages · One of the mental models for Haskell program main = exp aa (exp ab exp ac exp ad) exp ac = exp aca exp acb exp ad = exp ada exp adb exp

References : [H9], [D11], [H1] Ch.6, [S1]

“seq” doesn’t guarantee the evaluation order

specification

seq a b = ⊥, if a = ⊥

= b, otherwise

6. Semantics

seq ⊥ b = ⊥

seq a ⊥ = ⊥ // b is strict

// a is strict

“seq” function only guarantee that it is strict in both arguments.

This semantics property makes no operational guarantee about order of evaluation.

strictness for each arguments

Page 203: Lazy evaluation illustrated - GitHub Pages · One of the mental models for Haskell program main = exp aa (exp ab exp ac exp ad) exp ac = exp aca exp acb exp ad = exp ada exp adb exp

References : [H9], [D11], [H1] Ch.6, [S1]

“seq” and “pseq”

specification

seq a b = ⊥, if a = ⊥

= b, otherwise

seq ⊥ b = ⊥

seq a ⊥ = ⊥ // b is strict

6. Semantics

// a is strict

specification

pseq a b = ⊥, if a = ⊥

= b, otherwise

pseq ⊥ b = ⊥

pseq a ⊥ = ⊥ // b is strict

// a is strict

Both of denotational semantics are the same.

But “pseq” makes operational guarantee about order of evaluation.

Page 204: Lazy evaluation illustrated - GitHub Pages · One of the mental models for Haskell program main = exp aa (exp ab exp ac exp ad) exp ac = exp aca exp acb exp ad = exp ada exp adb exp

References : [H9], [D11], [H1] Ch.6, [S1]

Evaluation order of “seq” and “pseq”

seq a b

pseq a b

time

evaluation of a

evaluation of b

start termination

start termination return from b

no guarantee

no guarantee guarantee

time

evaluation of a

evaluation of b

start termination

start termination return from b

guarantee

6. Semantics

Page 205: Lazy evaluation illustrated - GitHub Pages · One of the mental models for Haskell program main = exp aa (exp ab exp ac exp ad) exp ac = exp aca exp acb exp ad = exp ada exp adb exp

References : [H9], [D11], [H1] Ch.6, [H2] Ch.7, [S1]

Implementation of “seq” and “pseq”

specification

seq a b = ⊥, if a = ⊥

= b, otherwise

Haskell’s built-in

6. Semantics

specification

pseq a b = ⊥, if a = ⊥

= b, otherwise

pseq x y = x `seq` lazy y

GHC’s “lazy” function restrains

the strictness analysis.

“seq” is built-in function.

“pseq” is implemented by built-in functions (“seq” and “lazy”).

Page 206: Lazy evaluation illustrated - GitHub Pages · One of the mental models for Haskell program main = exp aa (exp ab exp ac exp ad) exp ac = exp aca exp acb exp ad = exp ada exp adb exp

7. Appendix

Page 207: Lazy evaluation illustrated - GitHub Pages · One of the mental models for Haskell program main = exp aa (exp ab exp ac exp ad) exp ac = exp aca exp acb exp ad = exp ada exp adb exp

References

7. Appendix

Page 208: Lazy evaluation illustrated - GitHub Pages · One of the mental models for Haskell program main = exp aa (exp ab exp ac exp ad) exp ac = exp aca exp acb exp ad = exp ada exp adb exp

References

[H1] Haskell 2010 Language Report

https://www.haskell.org/definition/haskell2010.pdf

[H2] The Glorious Glasgow Haskell Compilation System (GHC user’s guide)

https://downloads.haskell.org/~ghc/latest/docs/users_guide.pdf

[H3] A History of Haskell: Being Lazy With Class

http://haskell.cs.yale.edu/wp-content/uploads/2011/02/history.pdf

[H4] The implementation of functional programming languages

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

[H5] Implementing lazy functional languages on stock hardware: the Spineless Tagless G-machine Version 2.5

http://research.microsoft.com/en-us/um/people/simonpj/Papers/spineless-tagless-gmachine.ps.gz

[H6] Making a Fast Curry Push/Enter vs Eval/Apply for Higher-order Languages

http://research.microsoft.com/en-us/um/people/simonpj/papers/eval-apply

[H7] Faster Laziness Using Dynamic Pointer Tagging

http://research.microsoft.com/en-us/um/people/simonpj/papers/ptr-tag/ptr-tagging.pdf

[H8] Measuring the effectiveness of a simple strictness analyser

http://research.microsoft.com/~simonpj/papers/simple-strictnes-analyser.ps.gz

[H9] Runtime Support for Multicore Haskell

http://community.haskell.org/~simonmar/papers/multicore-ghc.pdf

[H10] I know kung fu: learning STG by example

https://ghc.haskell.org/trac/ghc/wiki/Commentary/Compiler/GeneratedCode

7. Appendix

Page 209: Lazy evaluation illustrated - GitHub Pages · One of the mental models for Haskell program main = exp aa (exp ab exp ac exp ad) exp ac = exp aca exp acb exp ad = exp ada exp adb exp

References

[H11] GHC Commentary: The Layout of Heap Objects

https://ghc.haskell.org/trac/ghc/wiki/Commentary/Rts/Storage/HeapObjects

[H12] The ghc-prim package

https://hackage.haskell.org/package/ghc-prim

[H13] GHC Commentary: Strict & StrictData

https://ghc.haskell.org/trac/ghc/wiki/StrictPragma

[H14] The data type Type and its friends

https://ghc.haskell.org/trac/ghc/wiki/Commentary/Compiler/TypeType

[H15] Demand analyser in GHC

https://ghc.haskell.org/trac/ghc/wiki/Commentary/Compiler/Demand

[H16] Demand analysis

http://research.microsoft.com/en-us/um/people/simonpj/papers/demand-anal/demand.ps

[H17] Core-to-Core optimization pipeline

https://ghc.haskell.org/trac/ghc/wiki/Commentary/Compiler/Core2CorePipeline

[H18] The GHC reading list

https://ghc.haskell.org/trac/ghc/wiki/ReadingList

[H19] The GHC Commentary

https://ghc.haskell.org/trac/ghc/wiki/Commentary

7. Appendix

Page 210: Lazy evaluation illustrated - GitHub Pages · One of the mental models for Haskell program main = exp aa (exp ab exp ac exp ad) exp ac = exp aca exp acb exp ad = exp ada exp adb exp

References

[B1] Introduction to Functional Programming using Haskell (IFPH 2nd edition)

http://www.cs.ox.ac.uk/publications/books/functional/bird-1998.jpg

http://www.pearsonhighered.com/educator/product/Introduction-Functional-Programming/9780134843469.page

[B2] Thinking Functionally with Haskell (IFPH 3rd edition)

http://www.cs.ox.ac.uk/publications/books/functional/

[B3] Programming in Haskell

https://www.cs.nott.ac.uk/~gmh/book.html

[B4] Real World Haskell

http://book.realworldhaskell.org/

[B5] Parallel and Concurrent Programming in Haskell

http://chimera.labs.oreilly.com/books/1230000000929

[B6] Types and Programming Languages (TAPL)

https://mitpress.mit.edu/books/types-and-programming-languages

[B7] Purely Functional Data Structures

http://www.cambridge.org/us/academic/subjects/computer-science/programming-languages-and-applied-logic/purely-functional-data-structures

[B8] Algorithms: A Functional Programming Approach

http://catalogue.pearsoned.co.uk/catalog/academic/product/0,1144,0201596040,00.html

7. Appendix

Page 211: Lazy evaluation illustrated - GitHub Pages · One of the mental models for Haskell program main = exp aa (exp ab exp ac exp ad) exp ac = exp aca exp acb exp ad = exp ada exp adb exp

References

[D1] Laziness

http://dev.stephendiehl.com/hask/#laziness

[D2] Being Lazy with Class

http://www.seas.upenn.edu/~cis194/lectures/06-laziness.html

[D3] A Haskell Compiler

http://www.scs.stanford.edu/14sp-cs240h/slides/ghc-compiler-slides.html

http://www.scs.stanford.edu/11au-cs240h/notes/ghc-slides.html

[D4] Evaluation

http://dev.stephendiehl.com/fun/005_evaluation.html

[D5] Incomplete Guide to Lazy Evaluation (in Haskell)

https://hackhands.com/guide-lazy-evaluation-haskell

[D6] Laziness

https://www.fpcomplete.com/school/starting-with-haskell/introduction-to-haskell/6-laziness

[D7] Evaluation on the Haskell Heap

http://blog.ezyang.com/2011/04/evaluation-on-the-haskell-heap

[D8] Lazy Evaluation of Haskell

http://www.vex.net/~trebla/haskell/lazy.xhtml

[D9] Fixing foldl

http://www.well-typed.com/blog/2014/04/fixing-foldl

[D10] How to force a list

https://ro-che.info/articles/2015-05-28-force-list

7. Appendix

Page 212: Lazy evaluation illustrated - GitHub Pages · One of the mental models for Haskell program main = exp aa (exp ab exp ac exp ad) exp ac = exp aca exp acb exp ad = exp ada exp adb exp

References

[D11] Evaluation order and state tokens

https://www.fpcomplete.com/user/snoyberg/general-haskell/advanced/evaluation-order-and-state-tokens

[D12] Reasoning about laziness

http://blog.johantibell.com/2011/02/slides-from-my-talk-on-reasoning-about.html

[D13] Some History of Functional Programming Languages

http://www-fp.cs.st-andrews.ac.uk/tifp/TFP2012/TFP_2012/Turner.pdf

[D14] Why Functional Programming Matters

https://www.cs.kent.ac.uk/people/staff/dat/miranda/whyfp90.pdf

[D15] GHC illustrated

http://takenobu-hs.github.io/downloads/haskell_ghc_illustrated.pdf

7. Appendix

Page 213: Lazy evaluation illustrated - GitHub Pages · One of the mental models for Haskell program main = exp aa (exp ab exp ac exp ad) exp ac = exp aca exp acb exp ad = exp ada exp adb exp

References

[W1] Haskell/Laziness

https://en.wikibooks.org/wiki/Haskell/Laziness

[W2] Lazy evaluation

https://wiki.haskell.org/Lazy_evaluation

[W3] Lazy vs. non-strict

https://wiki.haskell.org/Lazy_vs._non-strict

[W4] Haskell/Denotational semantics

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

[W5] Haskell/Graph reduction

https://en.wikibooks.org/wiki/Haskell/Graph_reduction

[W6] Performance/Strictness

https://wiki.haskell.org/Performance/Strictness

7. Appendix

Page 214: Lazy evaluation illustrated - GitHub Pages · One of the mental models for Haskell program main = exp aa (exp ab exp ac exp ad) exp ac = exp aca exp acb exp ad = exp ada exp adb exp

References

[S1] Hackage

https://hackage.haskell.org

[S2] Hoogle

https://www.haskell.org/hoogle

7. Appendix

Page 215: Lazy evaluation illustrated - GitHub Pages · One of the mental models for Haskell program main = exp aa (exp ab exp ac exp ad) exp ac = exp aca exp acb exp ad = exp ada exp adb exp

Lazy,...

to be as lazy as possible...