Abstract Refinements

Very General Mechanism

Next: Lets add parameters...

Example: plus

25: {-@ plus :: x:_ -> y:_ -> {v:_ | v=x+y} @-}
26: x1:Int -> x2:Int -> {v : Int | (v == (x1 + x2))}plus Intx Inty = {x2 : Int | (x2 == x)}x x1:Int -> x2:Int -> {x4 : Int | (x4 == (x1 + x2))}+ {x2 : Int | (x2 == y)}y

Example: plus 3


36: {-@ plus3' :: x:Int -> {v:Int | v = x + 3} @-}
37: x1:Int -> {v : Int | (v == (x1 + 3))}plus3'     = x1:Int -> x2:Int -> {x2 : Int | (x2 == (x1 + x2))}plus {x2 : Int | (x2 == (3  :  int))}3


Easily verified by LiquidHaskell

A Composed Variant

Lets define plus3 by composition

Using (.) Operator


123: {-@ plus3 :: x:Int -> {v:Int | v = x + 3} @-}
124: plus3     = plus 1 . plus 2


LiquidHaskell instantiates

  • p with \x -> v = x + 1
  • q with \x -> v = x + 2

Using (.) Operator


138: {-@ plus3 :: x:Int -> {v:Int | v = x + 3} @-}
139: plus3     = plus 1 . plus 2


To infer that output of plus3 has type:

exists [z:{v = y + 2}].{v = z + 1}

<:

{v:Int|v=3}

Recap

  1. Refinements: Types + Predicates
  2. Subtyping: SMT Implication
  3. Measures: Strengthened Constructors
  4. Abstract: Refinements over Type Signatures
    • Dependencies using refinement parameters