O slideshow foi denunciado.
Utilizamos seu perfil e dados de atividades no LinkedIn para personalizar e exibir anúncios mais relevantes. Altere suas preferências de anúncios quando desejar.

Refinement types for haskell

539 visualizações

Publicada em

Type systems allow programmers to express certain properties about correct behavior of programs. These properties can be verified by a static type checking compiler guaranteeing type safety and thus catching many programming errors early in the development cycle.

Refinement types are an approach for expressing more detailed properties of types using logical predicates. We will introduce Liquid Haskell which is a static refinement type checker capable of veryfing refinement type safety. We will examine the possibilites this approach opens for increasing development productivity.

Publicada em: Software
  • Seja o primeiro a comentar

Refinement types for haskell

  1. 1. Refinement types for Haskell
  2. 2. Martin Ockajak from Zürich Software Engineer @martin_ockajak
  3. 3. Outline ● Motivation ● Refinement types ● Liquid Haskell ● Practical considerations
  4. 4. Motivation
  5. 5. 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 ?
  6. 6. 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
  7. 7. Refinement types
  8. 8. 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
  9. 9. Predicate ● Boolean operators ● && , || , not , => , <=> , true , false ● Arithmetic operators ● + , - , * , / , mod ● Relations ● == , /= , < , > , <= , >=
  10. 10. Liquid Haskell
  11. 11. 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/
  12. 12. 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 :: Int one = 1 {-@ odds :: [Odd] @-} odds :: [Int] odds = [1, 3, 7]
  13. 13. Refining function results {-@ two :: {v: Int | v mod 2 == 0 } @-} {-@ one, two :: NonZero @-} two :: Int two = 1 + 1 {-@ size :: [a] -> {v: Int | v >= 0 } @-} size :: [a] -> Int size [] = 0 size (x:xs) = 1 + size xs {-@ positive :: n:Int -> { v: Bool | Prop v <=> n > 0 } @-} positive :: Int -> Bool positive n = n > 0
  14. 14. Refining function arguments {-@ crash :: {v: String | false } -> a @-} crash :: String -> a crash message = error message {-@ divide :: Int -> NonZero -> Int @-} divide :: Int -> Int -> Int divide n 0 = crash "division by zero" divide n d = n `div` d correctDivide :: Int correctDivide = divide 1 1 incorrectDivide :: Int incorrectDivide = divide 1 0
  15. 15. 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 :: Int three = 5 - 2
  16. 16. 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 -> Int len Emp = 0 len (x:::xs) = 1 + len xs {-@ first :: {v: List a | len v > 0 } -> a @-} first Emp = crash "empty list" first (x:::xs) = x
  17. 17. 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)))
  18. 18. Inline functions and assumptions ● Inline functions can be used inside measures ● Assumptions allow describing non-verifiable functions {-@ inline increment2 @-} increment2 :: Int -> Int increment2 n = n + 2 {-@ measure doubleLen @-} doubleLen :: List a -> Int doubleLen Emp = 0 doubleLen (x:::xs) = increment2 (doubleLen xs) {-@ assume abs :: (Num a) => a -> {v: a | v > 0 } @-}
  19. 19. 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 -> a fact 0 = 1 fact n = n * fact (n – 1) correctFact = fact 3 incorrectFact = fact (-1)
  20. 20. Practical considerations
  21. 21. Practicality – Liquid Haskell ● Compatible with several SMT solvers ● Incremental checking support ● Decent documentation ● Still experimental
  22. 22. Thank you :-)

×