liquid resource types for verification and synthesisnpolikarpova/talks/lrt-chalmers...checking...

158
liquid resource types for verification and synthesis Nadia Polikarpova with Tristan Knoth, Di Wang, and Jan Hoffmann

Transcript of liquid resource types for verification and synthesisnpolikarpova/talks/lrt-chalmers...checking...

  • liquid resource typesfor verification and synthesis

    Nadia Polikarpovawith Tristan Knoth, Di Wang, and Jan Hoffmann

  • program synthesis

    2

    code

    specification

    components

  • type-driven program synthesis

    3

    code

    specification

    components

  • type-driven program synthesis

    3

    code

    specification

    components

  • type-driven program synthesis

    4

    code

    specification

    components

    liquid types

    synquid

  • type-driven program synthesis

    4

    code

    specification

    components

    liquid types

    synquid

  • example: compress a list

    5

  • example: compress a list

    input:

    5

    2 3 32 3 2

  • example: compress a list

    input:

    output:

    5

    2 3 32 3 2

    2 3 2

  • example: compress a list

    6

    2 3 32 3 2

  • example: compress a list

    6

    2 3 32 3 2

    22 3 2

  • example: compress a list

    6

    2 3 32 3 2

    2 3 2

    22 3 2

  • synthesizing compress

    7

    code

    ??specification

    components

  • compress :: xs: List a → {v:CList a | elems v = elems xs}

    compress: specification

    8

    CList aList a

  • compress :: xs: List a → {v:CList a | elems v = elems xs}

    compress: specification

    8

    CList a

    compressed list(no adjacent duplicates)

  • compress :: xs: List a → {v:CList a | elems v = elems xs}

    compress: specification

    8

    same set of elements

  • synthesizing compress

    9

    codecompress ::xs:List a →{v:CList a |elems v = elems xs}

    synquid

    specification

    components

    (==), List, CList

  • synthesizing compress

    9

    codecompress ::xs:List a →{v:CList a |elems v = elems xs}

    synquid

    specification

    components

    (==), List, CList

  • 19

    http://comcom.csail.mit.edu/demos/#compress

    http://comcom.csail.mit.edu/demos/#compress

  • compress: generated solution

    10

    compress xs =match xs with

    Nil → NilCons y ys →

    match compress ys withNil → Cons y NilCons z zs → if z == y

    then compress yselse Cons y (Cons z zs)

  • compress: generated solution

    10

    compress xs =match xs with

    Nil → NilCons y ys →

    match compress ys withNil → Cons y NilCons z zs → if z == y

    then compress yselse Cons y (Cons z zs)

  • compress: generated solution

    10

    compress xs =match xs with

    Nil → NilCons y ys →

    match compress ys withNil → Cons y NilCons z zs → if z == y

    then compress yselse Cons y (Cons z zs)

    Cons z zs

  • 11

    specification code

    compress a listO(2|xs|)

    synthesizing efficient programs

  • 11

    specification code

    compress a list

    compress a listin linear time O(|xs|)

    O(2|xs|)

    synthesizing efficient programs

  • 12

    compress a listin linear time O(|xs|)

    synthesizing efficient programs

    specification code

  • 12

    compress a listin linear time O(|xs|)

    synthesizing efficient programs

    specification code

    liquidresource

    types

  • 12

    compress a listin linear time O(|xs|)

    synthesizing efficient programs

    specification code

    liquidresource

    types

    resyn

  • this talk

    1. liquid types + resource bounds

    13

  • this talk

    1. liquid types + resource bounds

    2. type checking

    13

  • this talk

    1. liquid types + resource bounds

    2. type checking

    3. non-linear bounds

    13

  • this talk

    1. liquid types + resource bounds

    2. type checking

    3. non-linear bounds

    4. value-dependent bounds

    13

  • this talk

    1. liquid types + resource bounds

    2. type checking

    3. non-linear bounds

    4. value-dependent bounds

    13

    [PLDI’19]

  • this talk

    1. liquid types + resource bounds

    2. type checking

    3. non-linear bounds

    4. value-dependent bounds

    13

    [PLDI’19]

    [ICFP’20 ?]

  • this talk

    1. liquid types + resource bounds

    2. type checking

    3. non-linear bounds

    4. value-dependent bounds

    14

  • types + refinements

    15

    { v:Int | 0 ≤ v }

  • types + refinements

    15

    { v:Int | 0 ≤ v }

    refinement

  • types + refinements

    15

    { v:Int | 0 ≤ v }

    natural numbers

  • types + refinements

    15

    { v:Int | 0 ≤ v }List

    lists of nats

  • types + refinements + resources

    16

    { v:Int | 0 ≤ v | 1 }}

    refinement

  • types + refinements + resources

    16

    { v:Int | 0 ≤ v | 1 }

    refinement potential

  • types + refinements + resources

    16

    { v:Int | 0 ≤ v | 1 }List

    refinement potential

  • types + refinements + resources

    16

    { v:Int | 0 ≤ v | 1 }List

    lists of nats with length units of potential

  • synthesizing efficient programs

    17

    code

    specification

    components

    resyn

  • synthesizing efficient programs

    17

    code

    specification

    components

    resyn

    cost model

  • synthesizing efficient programs

    17

    code

    specification

    components

    resyn

    cost model

    resource bound

  • synthesizing efficient programs

    17

    code

    specification

    components

    resyn

    cost model

  • (==) :: x:a → y:{a| |1} →{v:Bool | v = (x == y)}

    compress: cost model

    18

    y:a →

  • (==) :: x:a → y:{a| |1} →{v:Bool | v = (x == y)}

    compress: cost model

    18

  • synthesizing efficient programs

    19

    code

    specification

    components

    resynresource bound

  • compress :: xs:List {a | | 1} →{v:CList a | elems v = elems xs}

    compress: resource bound

    20

    xs:List a

  • compress :: xs:List {a | | 1} →{v:CList a | elems v = elems xs}

    compress: resource bound

    20

  • synthesizing linear compress

    21

    code

    specification

    components

    (==) :: x:a → y:{a | | 1}→ {v:Bool | …}

    resyn

    O(|xs|)

    compress ::xs:List {a | | 1} →{v:CList a | …}

  • synthesizing linear compress

    21

    code

    specification

    components

    (==) :: x:a → y:{a | | 1}→ {v:Bool | …}

    resyn

    O(|xs|)

    compress ::xs:List {a | | 1} →{v:CList a | …}

  • 54

    http://comcom.csail.mit.edu/demos/#compress_linear

    http://comcom.csail.mit.edu/demos/#compress_linear

  • this talk

    1. liquid types + resource bounds

    2. type checking

    3. non-linear bounds

    4. value-dependent bounds

    22

  • checking compress (exponential)

    23

    compress :: List {a||1} → List a

  • checking compress (exponential)

    23

    compress :: List {a||1} → List a

    compress xs =match xs with

    Nil → NilCons y ys →

    match compress ys withNil → Cons y NilCons z zs → if z == y

    then compress yselse …

  • checking compress (exponential)

    24

    List a

    compress xs = match xs with

    Nil → NilCons y ys →

    match compress ys withNil → Cons y NilCons z zs → if z == y

    then compress yselse …

    xs: List {a||1}

    compress: List {a||1} → List a

    Context:

  • checking compress (exponential)

    24

    List a

    compress xs = match xs with

    Nil → NilCons y ys →

    match compress ys withNil → Cons y NilCons z zs → if z == y

    then compress yselse …

    xs: List {a||1}

    compress: List {a||1} → List a

    Context:

    idea: generate constraints that have a solution if

  • checking compress (exponential)

    24

    List a

    compress xs = match xs with

    Nil → NilCons y ys →

    match compress ys withNil → Cons y NilCons z zs → if z == y

    then compress yselse …

    we can partition resources in context

    xs: List {a||1}

    compress: List {a||1} → List a

    Context:

    idea: generate constraints that have a solution if

  • checking compress (exponential)

    24

    List a

    compress xs = match xs with

    Nil → NilCons y ys →

    match compress ys withNil → Cons y NilCons z zs → if z == y

    then compress yselse …

    we can partition resources in context

    between terms that require potential

    xs: List {a||1}

    compress: List {a||1} → List a

    Context:

    idea: generate constraints that have a solution if

  • checking compress (exponential)

    25

    List a

    compress xs = match xs with

    Nil → NilCons y ys →

    match compress ys withNil → Cons y NilCons z zs → if z == y

    then compress yselse …

    :

    xs: List {a||1}

    compress: List {a||1} → List a

    Context:

  • checking compress (exponential)

    25

    List a

    compress xs = match xs with

    Nil → NilCons y ys →

    match compress ys withNil → Cons y NilCons z zs → if z == y

    then compress yselse …

    :

    xs: List {a||1}

    compress: List {a||1} → List a

    Context:

  • checking compress (exponential)

    25

    List a

    compress xs = match xs with

    Nil → NilCons y ys →

    match compress ys withNil → Cons y NilCons z zs → if z == y

    then compress yselse …

    :

    xs: List {a||1}

    compress: List {a||1} → List a

    Context:

  • checking compress (exponential)

    25

    List a

    compress xs = match xs with

    Nil → NilCons y ys →

    match compress ys withNil → Cons y NilCons z zs → if z == y

    then compress yselse …

    xs: List {a||???}

    compress: …

    xs: List {a||???}

    compress: …

    +

    :

    xs: List {a||1}

    compress: List {a||1} → List a

    Context:

  • checking compress (exponential)

    26

    List a

    compress xs = match xs with

    Nil → NilCons y ys →

    match compress ys withNil → Cons y NilCons z zs → if z == y

    then compress yselse …

    xs: List {a||1}

    compress: … compress: …

    + xs: List {a||0}

    xs: List {a||1}

    compress: List {a||1} → List a

    Context:

  • checking compress (exponential)

    27

    List a

    compress xs = match xs :: List {a||1} with

    Nil → NilCons y ys →

    match compress ys withNil → Cons y NilCons z zs → if z == y

    then compress yselse …

    xs: List {a||1}

    compress: …

  • checking compress (exponential)

    27

    List a

    compress xs = match xs :: List {a||1} with

    Nil → NilCons y ys →

    match compress ys withNil → Cons y NilCons z zs → if z == y

    then compress yselse …

    destructing yieldsys: List {a||1}y: {a||1}

    xs: List {a||1}

    compress: …

  • checking compress (exponential)

    28

    List a

    compress xs = match xs with

    Nil → NilCons y ys →

    match compress ys withNil → Cons y NilCons z zs → if z == y

    then compress yselse …

    ys: List {a||1}

    compress: List {a||1} → List a

    y: {a||1}

    Context:

  • checking compress (exponential)

    29

    List a

    compress xs = match xs with

    Nil → NilCons y ys →

    match compress ys withNil → Cons y NilCons z zs → if z == y

    then compress yselse …

    ys: List {a||1}

    compress: List {a||1} → List a

    y: {a||1}

    Context:

  • checking compress (exponential)

    29

    List a

    compress xs = match xs with

    Nil → NilCons y ys →

    match compress ys withNil → Cons y NilCons z zs → if z == y

    then compress yselse …

    ys: List {a||p} ys: List {a||q}+

    ys: List {a||1}

    compress: List {a||1} → List a

    y: {a||1}

    Context:

  • checking compress (exponential)

    30

    List a

    compress xs = match xs with

    Nil → NilCons y ys →

    match compress (ys :: List {a||p}) withNil → Cons y NilCons z zs → if z == y

    then compress (ys :: List {a||q})else …

    ys: List {a||1}

    compress: List {a||1} → List a

    y: {a||1}

    Context:

  • ys: List {a||1}

    compress: List {a||1} → List a

    y: {a||1}

    Context:

    checking compress (exponential)

    31

    List a

    compress xs = match xs with

    Nil → NilCons y ys →

    match compress (ys :: List {a||p}) withNil → Cons y NilCons z zs → if z == y

    then compress (ys :: List {a||q})else …

    Constraints: ∃p,q:

    1 = p + q

    1. total potential must be partitioned

  • ys: List {a||1}

    compress: List {a||1} → List a

    y: {a||1}

    Context:

    checking compress (exponential)

    32

    List a

    compress xs = match xs with

    Nil → NilCons y ys →

    match compress (ys :: List {a||p}) withNil → Cons y NilCons z zs → if z == y

    then compress (ys :: List {a||q})else …

    Constraints: ∃p,q:

    1 = p + q

    p ≥ 12. p must be enough to call compress

  • ys: List {a||1}

    compress: List {a||1} → List a

    y: {a||1}

    Context:

    checking compress (exponential)

    33

    List a

    compress xs = match xs with

    Nil → NilCons y ys →

    match compress ys withNil → Cons y NilCons z zs → if z == y

    then compress (ys :: List {a||q})else …

    Constraints: ∃p,q:

    1 = p + q

    p ≥ 13. q must be enough to call compress

    q ≥ 1

  • ys: List {a||1}

    compress: List {a||1} → List a

    y: {a||1}

    Context:

    checking compress (exponential)

    34

    List a

    compress xs = match xs with

    Nil → NilCons y ys →

    match compress ys withNil → Cons y NilCons z zs → if z == y

    then compress yselse …

    Constraints: ∃p,q:

    1 = p + q

    p ≥ 1

    q ≥ 1

  • ys: List {a||1}

    compress: List {a||1} → List a

    y: {a||1}

    Context:

    checking compress (exponential)

    34

    List a

    compress xs = match xs with

    Nil → NilCons y ys →

    match compress ys withNil → Cons y NilCons z zs → if z == y

    then compress yselse …

    Constraints: ∃p,q:

    1 = p + q

    p ≥ 1

    q ≥ 1

  • checking compress (linear)

    35

    List a

    compress xs = match xs with

    Nil → NilCons y ys →

    match compress (ys :: List {a||1}) withNil → Cons y NilCons z zs → if z == (y :: {a||1})

    then Cons z zselse Cons y (Cons z zs)

    ys: List {a||1}

    compress: List {a||1} → List a

    y: {a||1}

    Context:

  • checking compress (linear)

    35

    List a

    compress xs = match xs with

    Nil → NilCons y ys →

    match compress (ys :: List {a||1}) withNil → Cons y NilCons z zs → if z == (y :: {a||1})

    then Cons z zselse Cons y (Cons z zs)

    all potential in ysgoes here

    ys: List {a||1}

    compress: List {a||1} → List a

    y: {a||1}

    Context:

  • checking compress (linear)

    35

    List a

    compress xs = match xs with

    Nil → NilCons y ys →

    match compress (ys :: List {a||1}) withNil → Cons y NilCons z zs → if z == (y :: {a||1})

    then Cons z zselse Cons y (Cons z zs)

    all potential in ysgoes here

    pays for comparison

    ys: List {a||1}

    compress: List {a||1} → List a

    y: {a||1}

    Context:

  • checking compress (linear)

    35

    List a

    compress xs = match xs with

    Nil → NilCons y ys →

    match compress (ys :: List {a||1}) withNil → Cons y NilCons z zs → if z == (y :: {a||1})

    then Cons z zselse Cons y (Cons z zs)

    all potential in ysgoes here

    pays for comparison

    no potential consumed here

    ys: List {a||1}

    compress: List {a||1} → List a

    y: {a||1}

    Context:

  • checking compress (linear)

    35

    List a

    compress xs = match xs with

    Nil → NilCons y ys →

    match compress (ys :: List {a||1}) withNil → Cons y NilCons z zs → if z == (y :: {a||1})

    then Cons z zselse Cons y (Cons z zs)

    all potential in ysgoes here

    pays for comparison

    no potential consumed here

    ys: List {a||1}

    compress: List {a||1} → List a

    y: {a||1}

    Context:

  • formally: context sharing

    36

    Γ = Γ1 + Γ2Γ1 ⊢ 𝑒 ∷ List 𝑇′Γ2 ⊢ 𝑒1 ∷ 𝑇

    Γ2, 𝑥: 𝑇′, 𝑥𝑠: List 𝑇′ ⊢ 𝑒1 ∷ 𝑇

    Γ ⊢ match 𝑒 with 𝑒1; 𝜆𝑥 𝑥𝑠. 𝑒2 ∷ 𝑇

  • formally: context sharing

    36

    Γ = Γ1 + Γ2Γ1 ⊢ 𝑒 ∷ List 𝑇′Γ2 ⊢ 𝑒1 ∷ 𝑇

    Γ2, 𝑥: 𝑇′, 𝑥𝑠: List 𝑇′ ⊢ 𝑒1 ∷ 𝑇

    Γ ⊢ match 𝑒 with 𝑒1; 𝜆𝑥 𝑥𝑠. 𝑒2 ∷ 𝑇

  • formally: context sharing

    36

    Γ = Γ1 + Γ2Γ1 ⊢ 𝑒 ∷ List 𝑇′Γ2 ⊢ 𝑒1 ∷ 𝑇

    Γ2, 𝑥: 𝑇′, 𝑥𝑠: List 𝑇′ ⊢ 𝑒1 ∷ 𝑇

    Γ ⊢ match 𝑒 with 𝑒1; 𝜆𝑥 𝑥𝑠. 𝑒2 ∷ 𝑇

  • formally: context sharing

    36

    Γ = Γ1 + Γ2Γ1 ⊢ 𝑒 ∷ List 𝑇′Γ2 ⊢ 𝑒1 ∷ 𝑇

    Γ2, 𝑥: 𝑇′, 𝑥𝑠: List 𝑇′ ⊢ 𝑒1 ∷ 𝑇

    Γ ⊢ match 𝑒 with 𝑒1; 𝜆𝑥 𝑥𝑠. 𝑒2 ∷ 𝑇

  • formally: context sharing

    36

    Γ = Γ1 + Γ2Γ1 ⊢ 𝑒 ∷ List 𝑇′Γ2 ⊢ 𝑒1 ∷ 𝑇

    Γ2, 𝑥: 𝑇′, 𝑥𝑠: List 𝑇′ ⊢ 𝑒1 ∷ 𝑇

    Γ ⊢ match 𝑒 with 𝑒1; 𝜆𝑥 𝑥𝑠. 𝑒2 ∷ 𝑇

  • formally: subtyping

    37

    Γ ⇒ 𝑟 ⇒ 𝑟′ Γ ⇒ 𝑝 ≥ 𝑝′

    Γ ⊢ 𝐵 𝑟 𝑝

  • formally: subtyping

    37

    Γ ⇒ 𝑟 ⇒ 𝑟′ Γ ⇒ 𝑝 ≥ 𝑝′

    Γ ⊢ 𝐵 𝑟 𝑝

  • formally: subtyping

    37

    Γ ⇒ 𝑟 ⇒ 𝑟′ Γ ⇒ 𝑝 ≥ 𝑝′

    Γ ⊢ 𝐵 𝑟 𝑝

  • this talk

    1. liquid types + resource bounds

    2. type checking

    3. non-linear bounds

    4. value-dependent bounds

    38

  • example: insertion sort

    39

    input: 5 28 3

  • example: insertion sort

    39

    8 35

    input:

    2

    5 28 3

  • example: insertion sort

    39

    8 35

    5

    input:

    2

    5 28 3

    2 83

  • example: insertion sort

    39

    8 35

    5

    input:

    2

    output:

    5 28 3

    2 83

    2 3 85

  • example: insertion sort

    39

    8 35

    5

    input:

    2

    output:

    5 28 3

    2 83

    2 3 85

    how many comparisons does insertion sort make?

  • example: insertion sort

    40

    sort xs =match xs withNil → NilCons y ys →

    insert y (sort ys)

  • example: insertion sort

    40

    insert x xs =match xs withNil → Cons x NilCons y ys →

    if x ≤ ythen Cons x xselse Cons y (insert x ys)

    sort xs =match xs withNil → NilCons y ys →

    insert y (sort ys)

  • example: insertion sort

    40

    insert x xs =match xs withNil → Cons x NilCons y ys →

    if x ≤ ythen Cons x xselse Cons y (insert x ys)

    sort xs =match xs withNil → NilCons y ys →

    insert y (sort ys)

    (≤) :: x:a → y:{a | | 1} → Bool

  • example: insertion sort

    40

    insert x xs =match xs withNil → Cons x NilCons y ys →

    if x ≤ ythen Cons x xselse Cons y (insert x ys)

    sort xs =match xs withNil → NilCons y ys →

    insert y (sort ys)

    insert :: a → List {a| |1} → List a

    (≤) :: x:a → y:{a | | 1} → Bool

  • example: insertion sort

    40

    insert x xs =match xs withNil → Cons x NilCons y ys →

    if x ≤ ythen Cons x xselse Cons y (insert x ys)

    sort xs =match xs withNil → NilCons y ys →

    insert y (sort ys)

    insert :: a → List {a| |1} → List a

    (≤) :: x:a → y:{a | | 1} → Bool

  • example: insertion sort

    40

    insert x xs =match xs withNil → Cons x NilCons y ys →

    if x ≤ ythen Cons x xselse Cons y (insert x ys)

    sort xs =match xs withNil → NilCons y ys →

    insert y (sort ys)

    insert :: a → List {a| |1} → List a

    (≤) :: x:a → y:{a | | 1} → Bool

    sort :: ???

  • example: insertion sort

    40

    insert x xs =match xs withNil → Cons x NilCons y ys →

    if x ≤ ythen Cons x xselse Cons y (insert x ys)

    sort xs =match xs withNil → NilCons y ys →

    insert y (sort ys)

    insert :: a → List {a| |1} → List a

    (≤) :: x:a → y:{a | | 1} → Bool

    sort :: ???

  • example: insertion sort

    40

    insert x xs =match xs withNil → Cons x NilCons y ys →

    if x ≤ ythen Cons x xselse Cons y (insert x ys)

    sort xs =match xs withNil → NilCons y ys →

    insert y (sort ys)

    insert :: a → List {a| |1} → List a

    (≤) :: x:a → y:{a | | 1} → Bool

    sort :: ???

    how can we assign more potential to the tail of list than the head?

  • data QList a whereNil :: QList aCons :: a →

    QList {a | | 1} →QList aList a →

    41

    inductive potentials

    List aList a

    List a

  • data QList a whereNil :: QList aCons :: a →

    QList {a | | 1} →QList aList a →

    41

    inductive potentials

    List aList a

    List a

    idea: annotate the datatypewith distribution of potential!

  • data QList a whereNil :: QList aCons :: a →

    QList {a | | 1} →QList aQList a →

    41

    inductive potentials

    idea: annotate the datatypewith distribution of potential!

  • data QList a whereNil :: QList aCons :: a →

    QList {a | | 1} →QList aQList a →

    41

    inductive potentials

    idea: annotate the datatypewith distribution of potential!

  • data QList a whereNil :: QList aCons :: a →

    QList {a | | 1} →QList a

    41

    inductive potentials

    idea: annotate the datatypewith distribution of potential!

  • data QList a whereNil :: QList aCons :: a →

    QList {a | | 1} →QList a

    41

    inductive potentials

    idea: annotate the datatypewith distribution of potential!

    one more unit of potential than a has

  • data QList a whereNil :: QList aCons :: a →

    QList {a | | 1} →QList a

    41

    inductive potentials

    idea: annotate the datatypewith distribution of potential!

    5 28 3 :: QList {Int | | 1}

    one more unit of potential than a has

  • data QList a whereNil :: QList aCons :: a →

    QList {a | | 1} →QList a

    41

    inductive potentials

    idea: annotate the datatypewith distribution of potential!

    5 28 3 :: QList {Int | | 1}1

    one more unit of potential than a has

  • data QList a whereNil :: QList aCons :: a →

    QList {a | | 1} →QList a

    41

    inductive potentials

    idea: annotate the datatypewith distribution of potential!

    5 28 3 :: QList {Int | | 1}1 2

    one more unit of potential than a has

  • data QList a whereNil :: QList aCons :: a →

    QList {a | | 1} →QList a

    41

    inductive potentials

    idea: annotate the datatypewith distribution of potential!

    5 28 3 :: QList {Int | | 1}1 2 3

    one more unit of potential than a has

  • data QList a whereNil :: QList aCons :: a →

    QList {a | | 1} →QList a

    41

    inductive potentials

    idea: annotate the datatypewith distribution of potential!

    5 28 3 :: QList {Int | | 1}1 2 3 4

    one more unit of potential than a has

  • data QList a whereNil :: QList aCons :: a →

    QList {a | | 1} →QList a

    41

    inductive potentials

    idea: annotate the datatypewith distribution of potential!

    5 28 3 :: QList {Int | | 1}1 2 3 4 𝑛(𝑛 + 1)

    2

    one more unit of potential than a has

  • checking sort

    42

    sort :: QList {a | | 1} → List a

    sort xs =match xs with

    Nil → NilCons y ys →

    insert y (sort ys)

  • checking sort

    43

    List a

    sort xs = match xs with

    Nil → NilCons y ys →

    insert y (sort ys)

    xs: QList {a||1}

    sort: QList {c||1} → List c

    Context:

    insert: b → List {b||1} → List b

  • checking sort

    44

    List a

    sort xs = match xs :: QList {a||1} with

    Nil → NilCons y ys →

    insert y (sort ys)

    xs: QList {a||1}

    sort: QList {c||1} → List c

    Context:

    insert: b → List {b||1} → List b

  • checking sort

    44

    List a

    sort xs = match xs :: QList {a||1} with

    Nil → NilCons y ys →

    insert y (sort ys)

    xs: QList {a||1}

    sort: QList {c||1} → List c

    Context:

    insert: b → List {b||1} → List b

    data QList t whereNil :: QList tCons :: t → QList {t||1} → QList t

  • checking sort

    44

    List a

    sort xs = match xs :: QList {a||1} with

    Nil → NilCons y ys →

    insert y (sort ys)

    xs: QList {a||1}

    sort: QList {c||1} → List c

    Context:

    insert: b → List {b||1} → List b

    so destructing yields

    ys: QList {a||2}y: {a||1}

    data QList t whereNil :: QList tCons :: t → QList {t||1} → QList t

    t = {a||1}

  • checking sort

    45

    List a

    sort xs = match xs with

    Nil → NilCons y ys →

    insert y (sort ys)

    sort: QList {c||1} → List c

    Context:

    insert: b → List {b||1} → List b

    ys: QList {a||2}y: {a||1}

  • checking sort

    46

    List a

    sort xs = match xs with

    Nil → NilCons y ys →

    insert y(sort (ys::QList{a||2}))

    sort: QList {c||1} → List c

    Context:

    insert: b → List {b||1} → List b

    ys: QList {a||2}y: {a||1}

  • checking sort

    47

    List a

    sort xs = match xs with

    Nil → NilCons y ys →

    insert y((sort::QList{a||2} → List {a||1}) (ys::QList{a||2}))

    sort: QList {c||1} → List c

    Context:

    insert: b → List {b||1} → List b

    ys: QList {a||2}y: {a||1}polymorphic

    recursion withc = {a||1}

  • checking sort

    48

    List a

    sort xs = match xs with

    Nil → NilCons y ys →

    insert y((sort ys) :: List {a||1})

    sort: QList {c||1} → List c

    Context:

    insert: b → List {b||1} → List b

    ys: QList {a||2}y: {a||1}polymorphic

    recursion withc = {a||1}

  • checking sort

    49

    List a

    sort xs = match xs with

    Nil → NilCons y ys →

    insert y ((sort ys) :: List {a||1})

    sort: QList {c||1} → List c

    Context:

    insert: b → List {b||1} → List b

    ys: QList {a||0}y: {a||1}

    enough linear potential to pay for insertwith b = a

  • quadratic insertion sort

    50

    insert x xs =match xs withNil → Cons x NilCons y ys →

    if x ≤ ythen Cons x xselse Cons y (insert x ys)

    sort xs =match xs withNil → NilCons y ys →

    insert y (sort ys)

    insert :: a → List {a| |1} → List asort :: QList {a| |1} → List a

  • 128

    http://comcom.csail.mit.edu/demos/#insertion_sort_coarse

    http://comcom.csail.mit.edu/demos/#insertion_sort_coarse

  • this talk

    1. liquid types + resource bounds

    2. type checking

    3. non-linear bounds

    4. value-dependent bounds

    51

  • insertion sort: fine-grained bound

    52

    insert x xs =match xs withNil → Cons x NilCons y ys →

    if x ≤ ythen Cons x xselse Cons y (insert x ys)

    sort xs =match xs withNil → NilCons y ys →

    insert y (sort ys)

    sort :: QList {a| |1} → List a insert :: a → List {a| |1} → List a

  • insertion sort: fine-grained bound

    52

    makes one comparison per element < x

    insert x xs =match xs withNil → Cons x NilCons y ys →

    if x ≤ ythen Cons x xselse Cons y (insert x ys)

    sort xs =match xs withNil → NilCons y ys →

    insert y (sort ys)

    sort :: QList {a| |1} → List a insert :: a → List {a| |1} → List a

  • insertion sort: fine-grained bound

    52

    makes one comparison per element < x

    makes one comparison per decreasing pair of elements

    insert x xs =match xs withNil → Cons x NilCons y ys →

    if x ≤ ythen Cons x xselse Cons y (insert x ys)

    sort xs =match xs withNil → NilCons y ys →

    insert y (sort ys)

    sort :: QList {a| |1} → List a insert :: a → List {a| |1} → List a

  • insertion sort: fine-grained bound

    52

    makes one comparison per element < x

    makes one comparison per decreasing pair of elements

    insert x xs =match xs withNil → Cons x NilCons y ys →

    if x ≤ ythen Cons x xselse Cons y (insert x ys)

    sort xs =match xs withNil → NilCons y ys →

    insert y (sort ys)

    sort :: QList {a| |1} → List a insert :: a → List {a| |1} → List asort :: ??? insert :: ???

  • value-dependent potential

    53

    { v:Int | 0 ≤ v | v }| 1 }

  • value-dependent potential

    53

    { v:Int | 0 ≤ v | v }

  • value-dependent potential

    53

    { v:Int | 0 ≤ v | v }

    nat with potential equal to its value

  • insert: fine-grained bound

    54

    insert x xs =match xs with

    Nil → Cons x NilCons y ys →

    if x ≤ ythen Cons x xselse Cons y (insert x ys)

    insert :: a → List {a | | 1} → List a

    makes one comparison per element < x

  • insert: fine-grained bound

    55

    insert x xs =match xs with

    Nil → Cons x NilCons y ys →

    if x ≤ ythen Cons x xselse Cons y (insert x ys)

    insert :: {a||1} → List {a||ite (v < x) 1 0} → List a

  • insert: fine-grained bound

    55

    insert x xs =match xs with

    Nil → Cons x NilCons y ys →

    if x ≤ ythen Cons x xselse Cons y (insert x ys)

    insert :: {a||1} → List {a||ite (v < x) 1 0} → List a

    only assign potential to elements < x

  • checking insert

    56

    List a

    insert x xs = match xs with

    Nil → Cons x NilCons y ys →

    if x ≤ ythen Cons x xselse Cons y (insert x ys)

    Context:

    ys: List {a||ite (v < x) 1 0}

    y: {a||ite (v < x) 1 0}

    x: {a||1}

    insert:{a||1}→ List {a||ite (v < x) 1 0} → List a

  • checking insert

    56

    List a

    insert x xs = match xs with

    Nil → Cons x NilCons y ys →

    if x ≤ ythen Cons x xselse Cons y (insert x ys)

    Context:

    ys: List {a||ite (v < x) 1 0}

    y: {a||ite (v < x) 1 0}

    x: {a||1}

    pays for comparison

    insert:{a||1}→ List {a||ite (v < x) 1 0} → List a

  • checking insert

    57

    List a

    insert x xs = match xs with

    Nil → Cons x NilCons y ys →

    if x ≤ ythen Cons x xselse Cons y (insert (x::{a||1}) ys)

    Context:

    insert:{a||1}→ List {a||ite (v < x) 1 0} → List a

    ys: List {a||ite (v < x) 1 0}

    y: {a||ite (v < x) 1 0}

    x: {a||0}

  • checking insert

    57

    List a

    insert x xs = match xs with

    Nil → Cons x NilCons y ys →

    if x ≤ ythen Cons x xselse Cons y (insert (x::{a||1}) ys)

    Context:

    insert:{a||1}→ List {a||ite (v < x) 1 0} → List a

    ys: List {a||ite (v < x) 1 0}

    y: {a||ite (v < x) 1 0}

    x: {a||0}

    equivalent to {a||1}in this branch

    y < x

  • insertion sort: fine-grained bound

    58

    insert x xs =match xs withNil → Cons x NilCons y ys →

    if x ≤ ythen Cons x xselse Cons y (insert x ys)

    sort xs =match xs withNil → NilCons y ys →

    insert y (sort ys)

    sort :: QList {a| |1} → List a

    insert :: {a||1} →List {a||ite (v < x) 1 0} → List asort :: ???

  • insertion sort: fine-grained bound

    58

    insert x xs =match xs withNil → Cons x NilCons y ys →

    if x ≤ ythen Cons x xselse Cons y (insert x ys)

    sort xs =match xs withNil → NilCons y ys →

    insert y (sort ys)

    sort :: QList {a| |1} → List a

    insert :: {a||1} →List {a||ite (v < x) 1 0} → List asort :: ???

  • sort: fine-grained bound

    59

    sort xs =match xs with

    Nil → NilCons y ys →

    insert y (sort ys)

    sort :: ISList {a||1} → List a

  • sort: fine-grained bound

    59

    sort xs =match xs with

    Nil → NilCons y ys →

    insert y (sort ys)

    sort :: ISList {a||1} → List a

    data ISList a whereNil :: ISList aCons :: x:a →

    ISList {a||ite (v < x) 1 0} →ISList t

  • sort: fine-grained bound

    59

    sort xs =match xs with

    Nil → NilCons y ys →

    insert y (sort ys)

    sort :: ISList {a||1} → List a

    data ISList a whereNil :: ISList aCons :: x:a →

    ISList {a||ite (v < x) 1 0} →ISList t

  • abstract potentials

    60

    data List a whereNil :: List aCons :: h:a →

    t:List a →List a

  • abstract potentials

    60

    data List a whereNil :: List aCons :: h:a →

    t:List a →List a

    idea: parameterize the datatypeby a potential function!

  • abstract potentials

    60

    data List a whereNil :: List aCons :: h:a →

    t:List a →List a

    idea: parameterize the datatypeby a potential function!

    List a where

  • abstract potentials

    60

    data List a whereNil :: List aCons :: h:a →

    t:List a →List a

    idea: parameterize the datatypeby a potential function!

    List a whereList a

    List a List {a||q h v} →

  • insertion sort: fine-grained bound

    61

    insert x xs =match xs withNil → Cons x NilCons y ys →

    if x ≤ ythen Cons x xselse Cons y (insert x ys)

    sort xs =match xs withNil → NilCons y ys →

    insert y (sort ys)

  • insertion sort: fine-grained bound

    61

    insert x xs =match xs withNil → Cons x NilCons y ys →

    if x ≤ ythen Cons x xselse Cons y (insert x ys)

    sort xs =match xs withNil → NilCons y ys →

    insert y (sort ys)

    insert :: {a||1}→ List {a||ite (v < x) 1 0} → List a

  • insertion sort: fine-grained bound

    61

    insert x xs =match xs withNil → Cons x NilCons y ys →

    if x ≤ ythen Cons x xselse Cons y (insert x ys)

    sort xs =match xs withNil → NilCons y ys →

    insert y (sort ys)

    insert :: {a||1}→ List {a||ite (v < x) 1 0} → List a

    sort :: List a → List a

  • insertion sort: fine-grained bound

    61

    insert x xs =match xs withNil → Cons x NilCons y ys →

    if x ≤ ythen Cons x xselse Cons y (insert x ys)

    sort xs =match xs withNil → NilCons y ys →

    insert y (sort ys)

    insert :: {a||1}→ List {a||ite (v < x) 1 0} → List a

    sort :: List a → List a

  • 157

    http://comcom.csail.mit.edu/demos/#insertion_sort

    http://comcom.csail.mit.edu/demos/#insertion_sort

  • liquid resource types

    1. liquid types + resource bounds

    2. type checking

    3. non-linear bounds

    4. value-dependent bounds

    62

    [PLDI’19]

    [ICFP’20 ?]