refinement types for haskell

22
Refinement types for Haskell

Upload: martin-ockajak

Post on 22-Jan-2018

379 views

Category:

Software


2 download

TRANSCRIPT

Page 1: Refinement types for haskell

Refinement types for Haskell

Page 2: Refinement types for haskell

Martin Ockajak from Zürich

Software Engineer

@martin_ockajak

Page 3: Refinement types for haskell

Outline

● Motivation

● Refinement types

● Liquid Haskell

● Practical considerations

Page 4: Refinement types for haskell

Motivation

Page 5: Refinement types for haskell

Standard type system

● Allows expressing certain properties of programs● Type safety

● Verifiable without running the program● Static type checking

● Integrated with the compilation

● Testing still needed

● Can we do better ?

Page 6: Refinement types for haskell

Possible improvements

● Prevent more programming errors● Division by zero

● Missing keys in maps

● Infinite loops

● Express properties of programs in greater detail

● Keep the ability to automatically verify type safety● Verification must be a decidable problem

● No proofs by the programmer required

Page 7: Refinement types for haskell

Refinement types

Page 8: Refinement types for haskell

Refinement types

● Consist of● Type

● Standard or refinement

● Predicate● Propositional logic

● Can describe valid inputs and outputs of functions● Type safe if the predicate is valid for all inputs

Page 9: Refinement types for haskell

Predicate

● Boolean operators● && , || , not , => , <=> , true , false

● Arithmetic operators● + , - , * , / , mod

● Relations● == , /= , < , > , <= , >=

Page 10: Refinement types for haskell

Liquid Haskell

Page 11: Refinement types for haskell

Liquid Haskell

● Static refinement type verifier● Completely automatic

● Translates refinement types into verification conditions● Satisfiability modulo theories formulas

● Uses an SMT solver to verify those conditions● Without executing the program or enumerating inputs

● Project at University of California - San Diego● http://goto.ucsd.edu/~rjhala/liquid/haskell/blog/about/

Page 12: Refinement types for haskell

Defining refinement types● Positive is a subtype of NonZero

● Positive values are a subset of NonZero values

{-@ type NonZero = {v: Int | v /= 0 } @-}{-@ type Positive = {v: Int | v > 0 } @-}{-@ type Odd = {v: Int | v mod 2 == 1 } @-}

{-@ one :: NonZero @-}{-@ one :: Positive @-}{-@ one :: Odd @-}one :: Intone = 1

{-@ odds :: [Odd] @-}odds :: [Int]odds = [1, 3, 7]

Page 13: Refinement types for haskell

Refining function results

{-@ two :: {v: Int | v mod 2 == 0 } @-}{-@ one, two :: NonZero @-}two :: Inttwo = 1 + 1

{-@ size :: [a] -> {v: Int | v >= 0 } @-}size :: [a] -> Intsize [] = 0size (x:xs) = 1 + size xs

{-@ positive :: n:Int -> { v: Bool | Prop v <=> n > 0 } @-}positive :: Int -> Boolpositive n = n > 0

Page 14: Refinement types for haskell

Refining function arguments

{-@ crash :: {v: String | false } -> a @-}crash :: String -> acrash message = error message

{-@ divide :: Int -> NonZero -> Int @-}divide :: Int -> Int -> Intdivide n 0 = crash "division by zero"divide n d = n `div` d

correctDivide :: IntcorrectDivide = divide 1 1

incorrectDivide :: IntincorrectDivide = divide 1 0

Page 15: Refinement types for haskell

Defining predicates

{-@ predicate Positive N = N > 0 @-}{-@ predicate Even N = N mod 2 == 0 @-}{-@ predicate PositiveOdd N = Positive N && not Even N @-}

{-@ type Even = { v: Int | Even v } @-}

{-@ three :: { v: Int | PositiveOdd v || v == 4 } @-}three :: Intthree = 5 - 2

Page 16: Refinement types for haskell

Measure functions● Can be used inside refinement type definitions● Single expression for every data constructor

● Propositional logic only

data List a = Emp | (:::) a (List a)

{-@ measure len @-}len :: List a -> Intlen Emp = 0len (x:::xs) = 1 + len xs

{-@ first :: {v: List a | len v > 0 } -> a @-}first Emp = crash "empty list"first (x:::xs) = x

Page 17: Refinement types for haskell

Refining data types● Parametrized type alias used to specify list length

data Triple a = Triple (List a)

{-@ type ListN a N = {v: List a | len v == N} @-}

{-@ data Triple a = Triple (ListN a 3) @-}

correctTriple = Triple (1 ::: (2 ::: (3 ::: Emp)))

Page 18: Refinement types for haskell

Inline functions and assumptions● Inline functions can be used inside measures● Assumptions allow describing non-verifiable functions

{-@ inline increment2 @-}increment2 :: Int -> Intincrement2 n = n + 2

{-@ measure doubleLen @-}doubleLen :: List a -> IntdoubleLen Emp = 0doubleLen (x:::xs) = increment2 (doubleLen xs)

{-@ assume abs :: (Num a) => a -> {v: a | v > 0 } @-}

Page 19: Refinement types for haskell

Recursion

{-@ type NonNegative a = {v: a | v >= 0 } @-}{-@ type Natural a = {v: a | v > 0 } @-}

{-@ fact :: (Integral a) => NonNegative a -> Natural a @-}fact :: (Integral a) => a -> afact 0 = 1fact n = n * fact (n – 1)

correctFact = fact 3

incorrectFact = fact (-1)

Page 20: Refinement types for haskell

Practical considerations

Page 21: Refinement types for haskell

Practicality – Liquid Haskell

● Compatible with several SMT solvers

● Incremental checking support

● Decent documentation

● Still experimental

Page 22: Refinement types for haskell

Thank you :-)