Kinds Are Calling Conventions P a ul Downen, Zen a M. Ariol a , Simon - - PowerPoint PPT Presentation

kinds are calling conventions
SMART_READER_LITE
LIVE PREVIEW

Kinds Are Calling Conventions P a ul Downen, Zen a M. Ariol a , Simon - - PowerPoint PPT Presentation

Kinds Are Calling Conventions P a ul Downen, Zen a M. Ariol a , Simon Peyton Jones, Rich a rd A. Eisenberg ICFP 2020, August 23 29 Ef f icient Function Calls P a r a meter P a ssing Techniques Ef f icient Function Calls P a r a meter P a ssing


slide-1
SLIDE 1

ICFP 2020, August 23—29

Kinds Are Calling Conventions

Paul Downen, Zena M. Ariola, Simon Peyton Jones, Richard A. Eisenberg

slide-2
SLIDE 2

Efficient Function Calls

Parameter Passing Techniques

slide-3
SLIDE 3

Efficient Function Calls

  • Representation — What & Where?

Parameter Passing Techniques

slide-4
SLIDE 4

Efficient Function Calls

  • Representation — What & Where?
  • Arity — How many?

Parameter Passing Techniques

slide-5
SLIDE 5

Efficient Function Calls

  • Representation — What & Where?
  • Arity — How many?
  • Levity (aka Evaluation Strategy) — When to

compute?

Parameter Passing Techniques

slide-6
SLIDE 6

Efficient Function Calls

  • Representation — What & Where?
  • Arity — How many?
  • Levity (aka Evaluation Strategy) — When to

compute?

Parameter Passing Techniques

Arity

slide-7
SLIDE 7

Determining Function Arity

f1, f2, f3, f4 :: Int -> Int -> Int Type suggests arity 2

slide-8
SLIDE 8

Determining Function Arity

f1 = \x -> \y -> let z = expensive x in y + z f1, f2, f3, f4 :: Int -> Int -> Int Type suggests arity 2

slide-9
SLIDE 9

Determining Function Arity

f1 = \x -> \y -> let z = expensive x in y + z

Arity 2

f1, f2, f3, f4 :: Int -> Int -> Int Type suggests arity 2

slide-10
SLIDE 10

Determining Function Arity

f1 = \x -> \y -> let z = expensive x in y + z

Arity 2

f2 = \x -> f1 x f1, f2, f3, f4 :: Int -> Int -> Int Type suggests arity 2

slide-11
SLIDE 11

Determining Function Arity

f1 = \x -> \y -> let z = expensive x in y + z

Arity 2

f2 = \x -> f1 x f1, f2, f3, f4 :: Int -> Int -> Int Type suggests arity 2 = \x -> \y -> f1 x y

slide-12
SLIDE 12

Determining Function Arity

f1 = \x -> \y -> let z = expensive x in y + z

Arity 2

f2 = \x -> f1 x

Arity 2

f1, f2, f3, f4 :: Int -> Int -> Int Type suggests arity 2 = \x -> \y -> f1 x y

slide-13
SLIDE 13

Determining Function Arity

f1 = \x -> \y -> let z = expensive x in y + z

Arity 2

f2 = \x -> f1 x

Arity 2

f3 = \x -> let z = expensive x in \y -> y + z f1, f2, f3, f4 :: Int -> Int -> Int Type suggests arity 2 = \x -> \y -> f1 x y

slide-14
SLIDE 14

Determining Function Arity

f1 = \x -> \y -> let z = expensive x in y + z

Arity 2

f2 = \x -> f1 x

Arity 2

f3 = \x -> let z = expensive x in \y -> y + z f1, f2, f3, f4 :: Int -> Int -> Int Type suggests arity 2 = \x -> \y -> f1 x y Hint: ‘expensive x’ may be costly, or even cause side effects

slide-15
SLIDE 15

Determining Function Arity

f1 = \x -> \y -> let z = expensive x in y + z

Arity 2

f2 = \x -> f1 x

Arity 2

f3 = \x -> let z = expensive x in \y -> y + z

Arity 1

f1, f2, f3, f4 :: Int -> Int -> Int Type suggests arity 2 = \x -> \y -> f1 x y Hint: ‘expensive x’ may be costly, or even cause side effects

slide-16
SLIDE 16

Determining Function Arity

f1 = \x -> \y -> let z = expensive x in y + z

Arity 2

f2 = \x -> f1 x

Arity 2

f3 = \x -> let z = expensive x in \y -> y + z

Arity 1

f4 = \x -> f3 x f1, f2, f3, f4 :: Int -> Int -> Int Type suggests arity 2 = \x -> \y -> f1 x y Hint: ‘expensive x’ may be costly, or even cause side effects

slide-17
SLIDE 17

Determining Function Arity

f1 = \x -> \y -> let z = expensive x in y + z

Arity 2

f2 = \x -> f1 x

Arity 2

f3 = \x -> let z = expensive x in \y -> y + z

Arity 1

f4 = \x -> f3 x f1, f2, f3, f4 :: Int -> Int -> Int Type suggests arity 2 = \x -> \y -> f1 x y ≠ \x -> \y -> f3 x y Hint: ‘expensive x’ may be costly, or even cause side effects

slide-18
SLIDE 18

Determining Function Arity

f1 = \x -> \y -> let z = expensive x in y + z

Arity 2

f2 = \x -> f1 x

Arity 2

f3 = \x -> let z = expensive x in \y -> y + z

Arity 1

f4 = \x -> f3 x

Arity 1

f1, f2, f3, f4 :: Int -> Int -> Int Type suggests arity 2 = \x -> \y -> f1 x y ≠ \x -> \y -> f3 x y Hint: ‘expensive x’ may be costly, or even cause side effects

slide-19
SLIDE 19

What Is Arity?

For Curried Functions

slide-20
SLIDE 20

What Is Arity?

Definition 1. The number of arguments a function needs before doing “serious work.”

For Curried Functions

slide-21
SLIDE 21

What Is Arity?

Definition 1. The number of arguments a function needs before doing “serious work.”

  • If ‘f 1 2 3’ does work, but ‘f 1 2’ does not, then ‘f’ has arity 3

For Curried Functions

slide-22
SLIDE 22

What Is Arity?

Definition 1. The number of arguments a function needs before doing “serious work.”

  • If ‘f 1 2 3’ does work, but ‘f 1 2’ does not, then ‘f’ has arity 3

Definition 2. The number of times a function may be soundly η-expanded.

For Curried Functions

slide-23
SLIDE 23

What Is Arity?

Definition 1. The number of arguments a function needs before doing “serious work.”

  • If ‘f 1 2 3’ does work, but ‘f 1 2’ does not, then ‘f’ has arity 3

Definition 2. The number of times a function may be soundly η-expanded.

  • If ‘f’ is equivalent to ‘\x y z -> f x y z’, then ‘f’ has arity 3

For Curried Functions

slide-24
SLIDE 24

What Is Arity?

Definition 1. The number of arguments a function needs before doing “serious work.”

  • If ‘f 1 2 3’ does work, but ‘f 1 2’ does not, then ‘f’ has arity 3

Definition 2. The number of times a function may be soundly η-expanded.

  • If ‘f’ is equivalent to ‘\x y z -> f x y z’, then ‘f’ has arity 3

Definition 3. The number of arguments passed simultaneously to a function during one call.

For Curried Functions

slide-25
SLIDE 25

What Is Arity?

Definition 1. The number of arguments a function needs before doing “serious work.”

  • If ‘f 1 2 3’ does work, but ‘f 1 2’ does not, then ‘f’ has arity 3

Definition 2. The number of times a function may be soundly η-expanded.

  • If ‘f’ is equivalent to ‘\x y z -> f x y z’, then ‘f’ has arity 3

Definition 3. The number of arguments passed simultaneously to a function during one call.

  • If ‘f’ has arity 3, then ‘f 1 2 3’ can be implemented as a single call

For Curried Functions

slide-26
SLIDE 26

What Is Arity?

Definition 1. The number of arguments a function needs before doing “serious work.”

  • If ‘f 1 2 3’ does work, but ‘f 1 2’ does not, then ‘f’ has arity 3

Definition 2. The number of times a function may be soundly η-expanded.

  • If ‘f’ is equivalent to ‘\x y z -> f x y z’, then ‘f’ has arity 3

Definition 3. The number of arguments passed simultaneously to a function during one call.

  • If ‘f’ has arity 3, then ‘f 1 2 3’ can be implemented as a single call

For Curried Functions

slide-27
SLIDE 27

Goal: An IL with unrestricted η for functions, along with restricted β for other types

slide-28
SLIDE 28

Static Arity

In an Intermediate Language

slide-29
SLIDE 29

Static Arity

  • New

type of primitive functions (ASCII ‘a ~> b’)

  • To distinguish from the source-level

with different semantics

a ⇝ b

a → b

In an Intermediate Language

slide-30
SLIDE 30

Static Arity

  • New

type of primitive functions (ASCII ‘a ~> b’)

  • To distinguish from the source-level

with different semantics

a ⇝ b

a → b

  • Primitive functions are fully extensional, unlike source functions
  • unconditionally

λx . f x =η f : a ⇝ b

In an Intermediate Language

slide-31
SLIDE 31

Static Arity

  • New

type of primitive functions (ASCII ‘a ~> b’)

  • To distinguish from the source-level

with different semantics

a ⇝ b

a → b

  • Primitive functions are fully extensional, unlike source functions
  • unconditionally

λx . f x =η f : a ⇝ b

  • Application may still be restricted for efficiency, like source functions
  • does not recompute

(λx . x + x) (fact 106) fact 106

In an Intermediate Language

slide-32
SLIDE 32

Static Arity

  • New

type of primitive functions (ASCII ‘a ~> b’)

  • To distinguish from the source-level

with different semantics

a ⇝ b

a → b

  • Primitive functions are fully extensional, unlike source functions
  • unconditionally

λx . f x =η f : a ⇝ b

  • Application may still be restricted for efficiency, like source functions
  • does not recompute

(λx . x + x) (fact 106) fact 106

  • With full η, types express arity — just count the arrows
  • has arity 2, no matter ’s definition

f : Int ⇝ Bool ⇝ String f

In an Intermediate Language

slide-33
SLIDE 33

Currying

When Partial Application Matters

slide-34
SLIDE 34

Currying

f3 :: Int ~> Int ~> Int
 f3 = \x -> let z = expensive x in \y -> y + z

When Partial Application Matters

slide-35
SLIDE 35

Currying

f3 :: Int ~> Int ~> Int
 f3 = \x -> let z = expensive x in \y -> y + z

  • Because of η, f3 now has arity 2, not 1!

When Partial Application Matters

slide-36
SLIDE 36

Currying

f3 :: Int ~> Int ~> Int
 f3 = \x -> let z = expensive x in \y -> y + z

  • Because of η, f3 now has arity 2, not 1!
  • map (f3 100) [1..10^6] recomputes ‘expensive 100’ a million times ☹

When Partial Application Matters

slide-37
SLIDE 37

Currying

f3 :: Int ~> Int ~> Int
 f3 = \x -> let z = expensive x in \y -> y + z

  • Because of η, f3 now has arity 2, not 1!
  • map (f3 100) [1..10^6] recomputes ‘expensive 100’ a million times ☹

f3’ :: Int ~> { Int ~> Int }
 f3’ = \x -> let z = expensive x in Clos (\y -> y + z)

When Partial Application Matters

Clos :: (Int ~> Int) ~> {Int ~> Int}

slide-38
SLIDE 38

Currying

f3 :: Int ~> Int ~> Int
 f3 = \x -> let z = expensive x in \y -> y + z

  • Because of η, f3 now has arity 2, not 1!
  • map (f3 100) [1..10^6] recomputes ‘expensive 100’ a million times ☹

f3’ :: Int ~> { Int ~> Int }
 f3’ = \x -> let z = expensive x in Clos (\y -> y + z)

  • f3’ is an arity 1 function; returns a closure {Int~>Int} of an arity 1 function

When Partial Application Matters

Clos :: (Int ~> Int) ~> {Int ~> Int}

slide-39
SLIDE 39

Currying

f3 :: Int ~> Int ~> Int
 f3 = \x -> let z = expensive x in \y -> y + z

  • Because of η, f3 now has arity 2, not 1!
  • map (f3 100) [1..10^6] recomputes ‘expensive 100’ a million times ☹

f3’ :: Int ~> { Int ~> Int }
 f3’ = \x -> let z = expensive x in Clos (\y -> y + z)

  • f3’ is an arity 1 function; returns a closure {Int~>Int} of an arity 1 function
  • map (App (f3’ 100)) [1..10^6] computes ‘expensive 100’ only once ☺

When Partial Application Matters

Clos :: (Int ~> Int) ~> {Int ~> Int} App :: {Int ~> Int} ~> Int ~> Int

slide-40
SLIDE 40

Functions are Called

Not Evaluated

slide-41
SLIDE 41

Functions are Called

Not Evaluated

x = let f :: Int ~> Int = expensive 100 in …f…f…

slide-42
SLIDE 42

Functions are Called

  • When is expensive 100 evaluated?

Not Evaluated

x = let f :: Int ~> Int = expensive 100 in …f…f…

slide-43
SLIDE 43

Functions are Called

  • When is expensive 100 evaluated?
  • Call-by-value: first, before binding f

Not Evaluated

x = let f :: Int ~> Int = expensive 100 in …f…f…

slide-44
SLIDE 44

Functions are Called

  • When is expensive 100 evaluated?
  • Call-by-value: first, before binding f
  • Call-by-need: later, but only once, when f is first demanded

Not Evaluated

x = let f :: Int ~> Int = expensive 100 in …f…f…

slide-45
SLIDE 45

Functions are Called

  • When is expensive 100 evaluated?
  • Call-by-value: first, before binding f
  • Call-by-need: later, but only once, when f is first demanded
  • Call-by-name: later, re-evaluated every time f is demanded

Not Evaluated

x = let f :: Int ~> Int = expensive 100 in …f…f…

slide-46
SLIDE 46

Functions are Called

  • When is expensive 100 evaluated?
  • Call-by-value: first, before binding f
  • Call-by-need: later, but only once, when f is first demanded
  • Call-by-name: later, re-evaluated every time f is demanded

Not Evaluated

x = let f :: Int ~> Int = expensive 100 in …f…f… x’ = let f :: Int ~> Int = \y -> expensive 100 y in …f…f…

slide-47
SLIDE 47

Functions are Called

  • When is expensive 100 evaluated?
  • Call-by-value: first, before binding f
  • Call-by-need: later, but only once, when f is first demanded
  • Call-by-name: later, re-evaluated every time f is demanded

Not Evaluated

x = let f :: Int ~> Int = expensive 100 in …f…f… x’ = let f :: Int ~> Int = \y -> expensive 100 y in …f…f…

  • x = x’ by η, and x’ always follows call-by-name order!
slide-48
SLIDE 48

Functions are Called

  • When is expensive 100 evaluated?
  • Call-by-value: first, before binding f
  • Call-by-need: later, but only once, when f is first demanded
  • Call-by-name: later, re-evaluated every time f is demanded

Not Evaluated

x = let f :: Int ~> Int = expensive 100 in …f…f… x’ = let f :: Int ~> Int = \y -> expensive 100 y in …f…f…

  • x = x’ by η, and x’ always follows call-by-name order!
  • Primitive functions are never just evaluated; they are always called
slide-49
SLIDE 49

The Problem With Polymorphism

And Static Compilation

slide-50
SLIDE 50

The Problem With Polymorphism

And Static Compilation

poly :: forall a. (Int ~> Int ~> a) ~> (a, a)
 poly f = let g :: Int ~> a = f 3 in (g 5, g 4)

slide-51
SLIDE 51

The Problem With Polymorphism

  • What are the arities of f and g? Counting arrows…

And Static Compilation

poly :: forall a. (Int ~> Int ~> a) ~> (a, a)
 poly f = let g :: Int ~> a = f 3 in (g 5, g 4)

slide-52
SLIDE 52

The Problem With Polymorphism

  • What are the arities of f and g? Counting arrows…
  • f :: Int ~> Int ~> a has arity 2

And Static Compilation

poly :: forall a. (Int ~> Int ~> a) ~> (a, a)
 poly f = let g :: Int ~> a = f 3 in (g 5, g 4)

slide-53
SLIDE 53

The Problem With Polymorphism

  • What are the arities of f and g? Counting arrows…
  • f :: Int ~> Int ~> a has arity 2
  • g :: Int ~> a has arity 1

And Static Compilation

poly :: forall a. (Int ~> Int ~> a) ~> (a, a)
 poly f = let g :: Int ~> a = f 3 in (g 5, g 4)

slide-54
SLIDE 54

The Problem With Polymorphism

  • What are the arities of f and g? Counting arrows…
  • f :: Int ~> Int ~> a has arity 2
  • g :: Int ~> a has arity 1
  • But what if a = Bool ~> Bool?

And Static Compilation

poly :: forall a. (Int ~> Int ~> a) ~> (a, a)
 poly f = let g :: Int ~> a = f 3 in (g 5, g 4)

slide-55
SLIDE 55

The Problem With Polymorphism

  • What are the arities of f and g? Counting arrows…
  • f :: Int ~> Int ~> a has arity 2
  • g :: Int ~> a has arity 1
  • But what if a = Bool ~> Bool?
  • f :: Int ~> Int ~> Bool ~> Bool has arity 3…

And Static Compilation

poly :: forall a. (Int ~> Int ~> a) ~> (a, a)
 poly f = let g :: Int ~> a = f 3 in (g 5, g 4)

slide-56
SLIDE 56

The Problem With Polymorphism

  • What are the arities of f and g? Counting arrows…
  • f :: Int ~> Int ~> a has arity 2
  • g :: Int ~> a has arity 1
  • But what if a = Bool ~> Bool?
  • f :: Int ~> Int ~> Bool ~> Bool has arity 3…
  • g :: Int ~> Bool ~> Bool has arity 2… oops…

And Static Compilation

poly :: forall a. (Int ~> Int ~> a) ~> (a, a)
 poly f = let g :: Int ~> a = f 3 in (g 5, g 4)

slide-57
SLIDE 57

The Problem With Polymorphism

  • What are the arities of f and g? Counting arrows…
  • f :: Int ~> Int ~> a has arity 2
  • g :: Int ~> a has arity 1
  • But what if a = Bool ~> Bool?
  • f :: Int ~> Int ~> Bool ~> Bool has arity 3…
  • g :: Int ~> Bool ~> Bool has arity 2… oops…
  • How to statically compile? Is ‘g 5’ a call? A partial application?

And Static Compilation

poly :: forall a. (Int ~> Int ~> a) ~> (a, a)
 poly f = let g :: Int ~> a = f 3 in (g 5, g 4)

slide-58
SLIDE 58

Arity Polymorphism

Kinds As Calling Conventions

slide-59
SLIDE 59

Arity Polymorphism

  • Generalize a::★ to a::TYPE r c

Kinds As Calling Conventions

slide-60
SLIDE 60

Arity Polymorphism

  • Generalize a::★ to a::TYPE r c
  • r::Rep is the runtime representation of a

Kinds As Calling Conventions

slide-61
SLIDE 61

Arity Polymorphism

  • Generalize a::★ to a::TYPE r c
  • r::Rep is the runtime representation of a
  • c::Conv is the calling convention of a

Kinds As Calling Conventions

slide-62
SLIDE 62

Arity Polymorphism

  • Generalize a::★ to a::TYPE r c
  • r::Rep is the runtime representation of a
  • c::Conv is the calling convention of a
  • a::TYPE Ptr Call[n] says a values are pointers with arity n (simplified)

Kinds As Calling Conventions

slide-63
SLIDE 63

Arity Polymorphism

  • Generalize a::★ to a::TYPE r c
  • r::Rep is the runtime representation of a
  • c::Conv is the calling convention of a
  • a::TYPE Ptr Call[n] says a values are pointers with arity n (simplified)

poly :: forall a::TYPE Ptr Call[2]. (Int ~> Int ~> a) ~> (a,a)
 poly f = let g :: Int ~> a = f 3 in (g 4, g 5)

Kinds As Calling Conventions

slide-64
SLIDE 64

Arity Polymorphism

  • Generalize a::★ to a::TYPE r c
  • r::Rep is the runtime representation of a
  • c::Conv is the calling convention of a
  • a::TYPE Ptr Call[n] says a values are pointers with arity n (simplified)

poly :: forall a::TYPE Ptr Call[2]. (Int ~> Int ~> a) ~> (a,a)
 poly f = let g :: Int ~> a = f 3 in (g 4, g 5)

  • f :: Int ~> Int ~> a :: TYPE Ptr Call[4] has arity 4

Kinds As Calling Conventions

slide-65
SLIDE 65

Arity Polymorphism

  • Generalize a::★ to a::TYPE r c
  • r::Rep is the runtime representation of a
  • c::Conv is the calling convention of a
  • a::TYPE Ptr Call[n] says a values are pointers with arity n (simplified)

poly :: forall a::TYPE Ptr Call[2]. (Int ~> Int ~> a) ~> (a,a)
 poly f = let g :: Int ~> a = f 3 in (g 4, g 5)

  • f :: Int ~> Int ~> a :: TYPE Ptr Call[4] has arity 4
  • g :: Int ~> a :: TYPE PTR Call[3] has arity 3

Kinds As Calling Conventions

slide-66
SLIDE 66

Arity Polymorphism

  • Generalize a::★ to a::TYPE r c
  • r::Rep is the runtime representation of a
  • c::Conv is the calling convention of a
  • a::TYPE Ptr Call[n] says a values are pointers with arity n (simplified)

poly :: forall a::TYPE Ptr Call[2]. (Int ~> Int ~> a) ~> (a,a)
 poly f = let g :: Int ~> a = f 3 in (g 4, g 5)

  • f :: Int ~> Int ~> a :: TYPE Ptr Call[4] has arity 4
  • g :: Int ~> a :: TYPE PTR Call[3] has arity 3

revapp :: forall (c::Conv) (r::Rep)
 (a::TYPE Ptr c) (b::TYPE r Call[1]).
 a ~> (a ~> b) ~> b
 revapp x f = f x

Kinds As Calling Conventions

slide-67
SLIDE 67

Arity Polymorphism

  • Generalize a::★ to a::TYPE r c
  • r::Rep is the runtime representation of a
  • c::Conv is the calling convention of a
  • a::TYPE Ptr Call[n] says a values are pointers with arity n (simplified)

poly :: forall a::TYPE Ptr Call[2]. (Int ~> Int ~> a) ~> (a,a)
 poly f = let g :: Int ~> a = f 3 in (g 4, g 5)

  • f :: Int ~> Int ~> a :: TYPE Ptr Call[4] has arity 4
  • g :: Int ~> a :: TYPE PTR Call[3] has arity 3

revapp :: forall (c::Conv) (r::Rep)
 (a::TYPE Ptr c) (b::TYPE r Call[1]).
 a ~> (a ~> b) ~> b
 revapp x f = f x

  • f :: a ~> b :: TYPE Ptr Call[2] has arity 2

Kinds As Calling Conventions

slide-68
SLIDE 68

Arity Polymorphism

  • Generalize a::★ to a::TYPE r c
  • r::Rep is the runtime representation of a
  • c::Conv is the calling convention of a
  • a::TYPE Ptr Call[n] says a values are pointers with arity n (simplified)

poly :: forall a::TYPE Ptr Call[2]. (Int ~> Int ~> a) ~> (a,a)
 poly f = let g :: Int ~> a = f 3 in (g 4, g 5)

  • f :: Int ~> Int ~> a :: TYPE Ptr Call[4] has arity 4
  • g :: Int ~> a :: TYPE PTR Call[3] has arity 3

revapp :: forall (c::Conv) (r::Rep)
 (a::TYPE Ptr c) (b::TYPE r Call[1]).
 a ~> (a ~> b) ~> b
 revapp x f = f x

  • f :: a ~> b :: TYPE Ptr Call[2] has arity 2
  • x :: a :: TYPE Ptr c is represented as a pointer

Kinds As Calling Conventions

slide-69
SLIDE 69

Even More

  • Levity Polymorphism
  • For when evaluation strategy doesn’t matter
  • Compiling Source

Intermediate Target

  • Via kind-directed η-expansion and register assignment
  • Type system for ensuring static compilation
  • Of definitions with arity, levity, and representation polymorphism

→ →

In the Paper

slide-70
SLIDE 70

Kinds capture the details of efficient calling conventions