Refinement types for ML By Tim Freeman, Frank Pfenning @ CMU

Download Report

Transcript Refinement types for ML By Tim Freeman, Frank Pfenning @ CMU

Refinement types for ML
By Tim Freeman, Frank Pfenning @ CMU
Presented by: Andrey Utis
The Dilemma
• Find the last element in a list:
fun last (x::nil) = x | last (x::L) = last(L);
• What is last(nil) ?
• Solution #1: exceptions
– non-exhaustive match failure (SML)
• Solution #2: refinement types
– last: `a non-empty-list -> `a
Refinement types
• A is a refinement of B iff every element of
type A also has type B
• Finding the best refinement type is
undecidable in general
– function can run M on x
• Solution: let the programmer specify the
refinement types
Example
• Standard list type:
datatype `a list = nil | cons of `a * `a list
• Non-empty list refinement type:
rectype `a nonemptylist = cons of `a * `a list
• Singleton list refinement type:
rectype `a singleton = cons(`a, nil)
Refinements as lattices
• We can think of refinements as lattices
list
singleton OR nil
singleton
nil
?
Decidability
• Decidable since the lattices have finite
depth
• This is why we needed refinements to be
specified by the programmer
Abstract Interpretation
• Perform abstract interpretation using the
lattice
• Need a “constructor” function – e.g. how do
we get a singleton from another type?
• This can be derived from the “rectype”
definition
Example of cons
• Singleton
cons(`a * nil) -> `a singleton
cons(`a * `a singleton) -> `a list
cons(`a * `a list) -> `a list
Functions & polymorphism
• How do we deal with functions?
– Contravariance
a->b refines c->d iff c refines a and b refines d
• Polymorphism – use bounded quantification
– 8 ra::a ra->ra
– almost the same as standard type inference
The algorithm
• First infer standard ML types, then refine
• Additional inference rules:
– contravariance
– refinement transitivity
Inference rules
• LOOP is used for successive
approximations of recursive function types
• The new inference rules:
– G |- LOOP(f, ly.e, ? , L)
– G |-LOOP(f, ly.e, C1, L); G,f:C1::L |-ly.e:C2::L
=> G |- LOOP(f, ly.e, C2, L)
– G |-LOOP(f, ly.e, C, L); G,f:C::L |-ly.e:C::L
=> G |- fix f. ly.e:C::L
Soundness
• Theorem: for all valid type environments G
and expressions e, if e evaluates to v and
G|- e:D::L then G|- v:D`::L for some D`  D
• Proof is by induction on the structure of G
Implementation
• There is an implementation for Mini-ML
• Theory vs Practice
datatype maybe = true|false|maybe
rectype tt=true and ff=false and tf=true|false
let f x = fun true->false | false -> x | maybe->false
Theory: f:maybe->maybe
Practice: f:maybe->ff
Conclusion
• Decidable version of type refinement
• Efficiency can be a problem
• Type refinements can be thought of as
implicit documentation
• May be used to make execution faster