Self-reference -- recursive types

F_{ %m }


  • %t ::= ... | %m %a. %t [%a]
  • e ::= ... | %l( self ).{ a1 = e_1, ..., a_n = e_n }

Type assignment

  • \ffrac{ %G |- e_i : %t_i \hspace{1cm} (i = 1..n) }{ %G |- %l( self ).{ a1 = %t_1,.., a_n = %t_n } \e %m%a.{ a1:%t_1,.., a_n : %t_n }[%a] }

Refinement

  • \ffrac{ %G, %a <= %b |- %s <= %t }{ %G |- %m %a.%s[%a] <= %m %b.%t [%b] }

slide: A calculus for recursive types


Object semantics -- fixed point $ %s = F[%s] $

  • \Y ( %l( self ).F( self ) ) : %s

Unrolling -- unraveling a type

  • %m %a.F[%a] = F[ %m %a.F[%a] ]

Example


  T = \%m \%a.{ a:int, c:\%a, b:\%a->\%a }
  T_1 = { a:int, c:T, b:T->T, d:bool }
  T_2 = \%m \%a.{ a:int, c:\%a, b:T->T, d:bool }
  T_3 = \%m \%a.{ a:int, c:\%a, b:\%a->\%a, d:bool } 
  

T_1, T_2 <= T, T_3 \not<= T \zline{(contravariance)}


slide: Recursive types -- examples


Inheritance -- C = P + M

Semantics -- $\Y(C) = \Y(%l( self ).M( self )(P( self )))$


slide: Inheritance semantics -- self-reference


Object inheritance -- dynamic binding

P = %l( self ).{ i = 5, id = self }
C = %l( self ).P( self ) \with { b = true }
\Y(P):%t where %t = %m %a.{ i:int, id:%a } and P:%t->%t

Simple typing -- \Y(C):%s = { i:int, id:%t, b:bool }
Delayed -- \Y(C):%s' = %m %a.{ i:int, id:%a, b:bool }
We have %s' <= %s \zline{(more information)}


slide: Object inheritance -- dynamic binding


Contravariance


  C = \%l( self ).P( self )  \with { b = true,
      eq = \%l(o).(o.i = self.i    and 
      o.b = self.b)
   } 
  

\Y(P) : %t where %t = %m %a.{ i:int, eq:%a -> bool }
\Y(C):%s where %s = %m %a.{ i:int, id:%a -> bool, b: bool }
However %s \not<= %t \zline{(subtyping error)}


slide: Object inheritance -- contravariance


Type dependency -- is polymorphic

F-bounded constraint %a <= F[%a]\n Object instantiation: \Y(P[%s]) for %s = %m t.F[t]\n We have P[%s]:%s -> F[%s] because F[%s] = %s


slide: Bounded type constraints


Inheritance


   P = \%L \%a <= F[\%a].\%l( self: \%a).{ ... }
   C = \%L \%a <= G[\%a].\%l( self:\%a).P[\%a]( self ) \with { ... }
  

with recursive types
F[%a] = { i:int, id:%a -> bool }
G[%a] = { i:int, id:%a -> bool, b : bool }
Valid, because G[%a] <= F[%a]
However \Y(C[%s]) \not<=_{subtype} \Y(P[%t])


slide: Inheritance and constraints


Inheritance != subtyping

Eiffel



  class C inherit P redefine eq 
  feature
    b : Boolean is true;
    eq( other : like Current ) : Boolean is
    begin
        Result := (other.i = Current.i) and
  		  (other.b = Current.b)
    end
  end C
  

slide: Inheritance and subtyping in Eiffel



  p,v:P, c:C 
  
  v:=c; 
  v.eq(p);   // error p has no b 
  

slide: Example



  class C : public P { 
C++
int b; public: C() { ... } bool eq(C& other) { return other.i == i && other.b == b; } bool eq(P& other) { return other.i == i; } };

slide: Inheritance and subtyping in C++