Dependenent Types in Practicle programming

♥ Thanks Giving

Lesly Lamport

 

"Unfortunately one often pays a price for [languages which impose no   discipline of types] in the time taken to find rather inscrutable bugs,   anyone who mistakenly applies CDR to an atom in LISP & finds himself absurdly   adding a property list to an integer, will know the symptoms ". – Robin Milner
Some Advantages of Types :  
1. Detecting program errors at compile-time.

2. Enabling compiler optimizations.

3. Facilitating program verification :

   ▹ Using types to encode program properties   
   ▹ Verifying the encoded properties via type-checking

4. Serving as program documentation.
  

♥ ML {metalanguage}

									
▹ Developed by Robin Milner and others in 
  the early '70s @University of Edinburgh

▹ Well-designed type system.
                
▹ Hindley–Milner type system :
   Type inference algo can automatically
   assign the types of most expressions 
   without requiring explicit type annotations.   
   

Our Favorite ML Program


append : 'alist-> 'alist-> 'alist
fun append (nil, l2) = l2 
   | append (x::xs, l2) = x::append(xs, l2);
   

Type Systems:

 
♥ Rich , Realistic Languages * Simple Type system * 
         SML , OCaml, Haskell
     ^ Type Checking is Decidable.
       
♥ Small , Pure Languages * Richer Type theories * 
         Those underlying Coq, NuPrl , PX
       
     ^ Type checking is generally Undecidable
       or requires extensive verbose annotations.
         
 
Shortcomings of Realistic Languages. 

Only relatively elementary properties of program 
can be expressed and thus checked by a type checker. 

Eg : The error of taking the first element 
    out of an empty list can not be prevented 
    by ML type system.    


TradeOff : "Expressibility Vs Decidability"
Or write extensive verbose annotations.
♥ Goal :  
    " Designing a type system for practical programming
     in which a restricted form of dependent types is 
     available, allowing more program invariants to be 
     captured by types".

    Conservatively extend the type system of ML 
    by allowing some dependencies while maintaining 
    practical & unintrusive type-checking.
 

♥ Overview of Paper


Enriching the type system of ML with a restricted 
form of dependent types, where type index objects 
are drawn from a constraint domain C, leading to 
the DML(C) language schema.
    
    ▹ More Precise Type information.
    
    ▹ Facilitates Program error detection.
    
    ▹ Complier Optimisation.
    
Start Point ML0
base types d ::= int | bool | (user defined datatypes)
types t ::= d | t1 -> t2 | t1 * t2
patterns p ::= x | c(p) | <> | 
match clauses ms ::= (p => e) | (p => e | ms)

expressions 
       e ::= x | f | c | if (e, e1, e2) | <> |  |
             lam x:t. e | fix f:t. e | e1(e2) |
             let x=e1 in e2 end | case e of ms
                
values  v ::= x | c |  | lam x:t. e
context  Γ ::= . | Γ, x: t

Dependent Types :

 Dependent types are "types that depend on elements 
           of other types". 
Example :
▹ Type An of vectors of length n with components of type A
  Type An depends on the number n,  or that
  An is a "family of types indexed by the number n".

▹ Type Am × n of m × n-matrices. 
  
▹ Type of trees of a certain height.
  
▹  x:Nat, y:Seq(x) |- ...

• Our Favorite ML function Is back :

 

Our Favorite ML function : 
    append: ’alist -> ’alist -> ’alist
  
A correct implementation of the append function on lists
sld return a list of length m + n when given two lists
of length m and n. This property cannot be captured by 
the type system of ML(above type).

• Reason abt list lengths with restricted form of dep types

 append : ’alist(m) -> ’alist(n) -> ’alist(m + n)
             m,n are index objects

Full Example :

datatype ’a list = nil | cons of ’a * ’a list
          
typeref ’a list of nat with 
(* indexing the datatype ’a list with nat *)
    nil <| ’a list(0)
  | cons <| {n:nat} ’a * ’a list(n) -> ’a list(n+1)
          
fun(’a)
    append(nil, ys) = ys
  | append(cons(x, xs), ys) = cons(x, append(xs, ys))
where append <| {m:nat}{n:nat} ’a list(m) * ’a list(n)
                 -> ’a list(m+n)
                 
The declared type constructor list takes a type τ
and a type index n(of sort int) to form a type (τ)list(n)
for lists of length n in which each element is of type τ. 

The constructors of ’a list are then assgn depent types:

• nil <| ’a list(0)
(* nil is an ’a list of length 0. *)cons <| {n:nat} ’a * ’a list(n) -> ’a list(n+1) 
(* cons yields an ’a list of length n+1 when given a pair 
consisting of an elem of type ’a & an ’a list of lengt n *)

 {n:nat} is dependent function type constructor, 
 written as Πn : nat. Seen as universal quantifier. 

 The where clause in the declaration of
 append is a type annotation, which precisely states
 that append returns a list of length m + n.

Constraint Domains :
 
Traditionally, index objects are language expressions.

• Instead our lang is "parameterize over a domain of 
  constraints" from which type index objects are drawn.

 Examples include:
   • Linear inequalities over integers
   • Boolean constraints
   • Finite Sets

    Integer Constraint Domain
: We use a for index variables. index expressions i, j ::= a | c | i + j | i – j | i * j | i / j | … index propositions P, Q ::= i < j | i <= j | i > j | i >= j | i = j | i <> j | P ∧ Q | P ∨ Q index sorts γ ::= int | {a : γ | P } index variable contexts φ ::= . | φ, a: γ | φ, P index constraints Φ ::= P | P ⊃ Φ | ∀a: γ. Φ satisfaction relation φ |= Φ

Index sort :

Constraints themselves are typed. 

We call the types of the constraint lang "index sorts".

Here {a : γ | P} is the subset index sort
for those elements of γ satisfying proposition P.

For instance, nat is an abbreviation for 
 {a : int | a ≥ 0}.

The satisfaction relation φ |= Φ means that Φ is sat
 in the constraint domain under index context φ.

Important Points :
					 ♥ Family of types Indexed by type
	
  1.Distinction between two water Tight worlds.
    
  2.Type checking reduced to Constraint Solving.
	 
  3.Property became  Physical Value

  4.Decleration common type definition :  refactoring
					

Universal Dependent Types :


families δ ::= families of builtin,user-dec refined type
constructor signature S ::= · | S, c : Πa1 : γ1
                                 . . . Πan : γm.τ → δ(i)
major types µ ::= δ(i) | (τ1 ∗ τ2) | (τ1 → τ2)

types τ ::= µ | (Πa : γ.τ)

For instance, int(0), bool array(16);
   nat = [a:int | a >= 0] int(a);
   {a:int | a >= 0} int list(a) -> int list(a)
				
 Typing Rule and Judgement :
typing judgment  φ;Γ |- e : t 
                   φ |- τ1 ≡ τ2
                  
 φ;Γ |= e:τ1  φ |= τ1 ≡ τ2
---------------------------
      φ;Γ |= e:τ2

φ- index context , Γ- type context

#  For rest refer Paper #
An expression in MLΠ0 (C):
fix append : Πm : nat.Πn :
      nat.intlist(m) ∗ intlist(n) → intlist(m + n).
  λm : nat.λn : nat.lam l : intlist(m) ∗ intlist(n).
     case l of
       〈nil,ys〉 ⇒ ys
       〈cons[a](〈x , xs〉), ys〉  ⇒ 
          〈cons[a + n](〈x, append[a][n](〈xs,ys〉)〉)

Lets Type Check It :

 

Problem ?  
If we apply the filter function to a list of length n,
we cannot express the length of the resulting list
since it depends on the predicate p.

What happens when we can’t check list length?
   filter : (’a -> bool) ’a list(n) -> ’a list(?)
   
Solution Existential Dependent Types :
 ∃m ≤ n such that the length of the returned list is m.

** NOt Going into Details **

Constructing DML(C) :


    ML 0 ← MLΠ 0 ← ML0 Π,Σ ← DML(C)

• ML 0:
    • Explicitly typed
    • Overly verbose
    • Type checking is reduced to constraint
      satisfaction in C
• ML0 Π
      - Add universal dependent types
• ML0 Π,Σ
      - Add Existential types

Red-Black Trees :


Recall Red-Black Trees:

• Every node is either red or black.
• All leaves are black.
• For every node the black height of its children is equal
• Both children of any red node are black.

Red-Black Trees :

type ’a entry = int * ’a
datatype ’a dict =
  |  Empty (*consideredblack*)
  |  Black of ’a entry * ’a dict * ’a dict
  |  Red of ’a entry * ’a dict * ’a dict

typeref ’a dict of bool * nat with
  |  Empty <| ’a dict(true,0)
  |  Black <| {cl:bool}{cr:bool}{bh:nat} ’a entry * 
   ’a dict(cl,bh) * ’a dict(cr,bh) -> ’a dict(true,bh+1)
  |  Red <| {bh:nat}  ’a entry * ’a dict(true,bh)
    * ’a dict(true,bh) -> ’a dict(false,bh)

Dead Code Elimination :


exception zipException
fun(’a,’b)
   | zip(nil,nil) = nil
   | zip(cons(x,xs),cons(y,ys)) =
         cons((x,y),zip(xs,ys))
   | zip( _,_ ) = raisezipException
   

dependent types

By ashleel baba

dependent types

Dependent ML DML0(C)

  • 1,393