parameterized modules for classes and extensible functions

36
1 Parameterized Modules for Classes and Extensible Functions Keunwoo Lee Craig Chambers University of Washington FOOL/WOOD workshop, Jan. 2006 /ke • noo/ computational nihilist (grad student) (advisor)

Upload: roden

Post on 15-Jan-2016

33 views

Category:

Documents


0 download

DESCRIPTION

/ke • noo/. Parameterized Modules for Classes and Extensible Functions. Keunwoo Lee Craig Chambers University of Washington FOOL/WOOD workshop, Jan. 2006. computational nihilist (grad student). (advisor). Consider a module…. module Lang = { abstract class Expr of {} - PowerPoint PPT Presentation

TRANSCRIPT

Page 1: Parameterized Modules for Classes and Extensible Functions

1

Parameterized Modules for Classes and

Extensible Functions

Keunwoo Lee

Craig Chambers

University of Washington

FOOL/WOOD workshop, Jan. 2006

/ke • noo/

computational nihilist (grad student)

(advisor)

Page 2: Parameterized Modules for Classes and Extensible Functions

2

Consider a module…

module Lang = { abstract class Expr of {} abstract fun eval:Expr ! Int }

Page 3: Parameterized Modules for Classes and Extensible Functions

3

Desideratum 1:Data type extensibility

module C = { class Const extends Lang.Expr of {value:Int} extend fun Lang.eval(Const {value=v}) = v }

module Lang = { abstract class Expr of {} abstract fun eval:Expr ! Int }

Page 4: Parameterized Modules for Classes and Extensible Functions

4

Desideratum 2:Function extensibility

module P = {

fun print:Lang.Expr ! String

extend fun print(Lang.Expr) = "" }

module Lang = { abstract class Expr of {} abstract fun eval:Expr ! Int }

module C = { class Const extends Lang.Expr of {value:Int} extend fun Lang.eval(Const {value=v}) = v }

Page 5: Parameterized Modules for Classes and Extensible Functions

5

class Plus extends L.Expr of {left:L.Expr, right:L.Expr} extend fun L.eval(Plus {left, right}) = …

Desideratum 3:Reusable extensions

module Lang = { abstract class Expr of {} abstract fun eval:Expr ! Int }

signature LangSig = sig { abstract class Expr of {} abstract fun eval:Expr ! Int }

module MakePlus = (L:LangSig) ! {

}

module Plus = MakePlus(Lang)

module Plus = MakePlus(Lang) (* {

class Plus extends Lang.Expr of {left:Lang.Expr, right:Lang.Expr} extend fun Lang.eval(Plus …) … } *)

module Lang = { abstract class Expr of {} abstract fun eval:Expr ! Int }

Page 6: Parameterized Modules for Classes and Extensible Functions

6

module Plus = MakePlus(Lang)

Desideratum 4:Modular typechecking

sig { abstract class Expr of {} abstract fun eval:Expr ! Int }

signature LangSig = sig { abstract class Expr of {} abstract fun eval:Expr ! Int }

module MakePlus = (L:LangSig) ! { class Plus extends L.Expr of {left:L.Expr, right:L.Expr} extend fun L.eval(Plus {left, right}) = … }

module Lang = { abstract class Expr of {} abstract fun eval:Expr ! Int }

Page 7: Parameterized Modules for Classes and Extensible Functions

7

Desiderata summary

1. Data type extensibility2. Function extensibility3. Reusable extensions4. Modular typechecking

Page 8: Parameterized Modules for Classes and Extensible Functions

8

Related work• ML module system [MacQueen 84, …, Dreyer+03]

– No nontrivial extensible datatypes or functions

• OO module systems: Jiazzi [McDirmid+01], JavaMod [Ancona/Zucca01], etc.– Single-dispatch; function extensibility via design pattern

• OO parameterized classes:– Multiple inheritance, mixins [Bracha/Cook90], traits

[Schärli+03,etc.]– Virtual types [Madsen/Møller-Pedersen89]: gbeta [Ernst01],

Scala [Odersky+04], etc.– Single-dispatch; function extensibility via design pattern

Page 9: Parameterized Modules for Classes and Extensible Functions

9

Previous work: EML[Millstein et al., ICFP'02]

• Extensible datatypes/functions, modular typechecking

• A simple, restrictive parameterized module system

• Present work: F(EML)– extension of EML with much more useful

functors

Page 10: Parameterized Modules for Classes and Extensible Functions

10

Outline

• Desiderata• Signatures: key issues• Solutions• Conclusions

Page 11: Parameterized Modules for Classes and Extensible Functions

11

module Plus = MakePlus(Lang)

MakePlus, revisited

sig { abstract class Expr of {} abstract fun eval:Expr ! Int }

signature LangSig = sig { abstract class Expr of {} abstract fun eval:Expr ! Int }

module MakePlus = (L:LangSig) ! { class Plus extends L.Expr of {left:L.Expr, right:L.Expr} extend fun L.eval(Plus {left, right}) = … }

module Lang = { abstract class Expr of {} abstract fun eval:Expr ! Int }

Page 12: Parameterized Modules for Classes and Extensible Functions

12

A straw man signature calculus

Signatures are compatible iff:• Exact syntactic match on declarations• Width subtyping: freely permit subsumption to

"forget" extra declarations

Both inflexible and unsound

Page 13: Parameterized Modules for Classes and Extensible Functions

13

Signatures: Key issues

sig { abstract class Expr of {} abstract fun eval:Expr ! Int }

signature LangSig = sig { abstract class Expr of {} abstract fun eval:Expr ! Int }

Signatures constrain:• Names and modularization

choices

·

) alias declarationsmodule Lang' = { alias class Expr = Foo.Exp alias fun eval = Bar.eval }

Page 14: Parameterized Modules for Classes and Extensible Functions

14

Signatures: Key issues

sig {

abstract class Expr

extends Object of {}

abstract fun eval:Expr ! Int }

signature LangSig = sig { abstract class Expr of {} abstract fun eval:Expr ! Int }

signature LangSig = sig { abstract class Expr < Object of {} abstract fun eval:Expr ! Int }

·

Signatures constrain:• Names and modularization

choices• Relationships among

declarations/types) richer relation

language

Page 15: Parameterized Modules for Classes and Extensible Functions

15

Signatures: Key issues

sig { abstract class Expr extends Object of {} abstract fun eval:Expr ! Int abstract fun f:Expr ! String }

signature LangSig = sig { abstract class Expr extends Object of {} abstract fun eval:Expr ! Int }

Signatures constrain:• Names and modularization

choices• Relationships among

declarations/types

• Extra parts that may be ignored

) width subtyping via sealing

Page 16: Parameterized Modules for Classes and Extensible Functions

16

Signatures: Key issues

) alias declarations

) richer relation language

) width subtyping via sealing

Signatures constrain:• Names and modularization

choices• Relationships among

declarations/types

• Extra parts that may be ignored

Page 17: Parameterized Modules for Classes and Extensible Functions

17

Outline

• Desiderata• Signatures: key issues• Solutions

– Enriched relations– Sealing for subsumption

• Conclusions

Page 18: Parameterized Modules for Classes and Extensible Functions

18

Class relations

signature LangSig = sig { abstract class Expr of {} abstract fun eval:Expr ! Int }

module Lang = { abstract class Expr of {} abstract fun eval:Expr ! Int }

module MakePlus = (L:LangSig) ! { class Plus extends L.Expr of {left:L.Expr, right:L.Expr} extend fun L.eval(Plus {left, right}) = … }

Page 19: Parameterized Modules for Classes and Extensible Functions

19

Class relations

signature BOSig = sig { abstract class BinOp extends Lang.Expr of … }

module Lang = { abstract class Expr of {} abstract fun eval:Expr ! Int }

module MakePlus = (O:BOSig) ! { class Plus extends O.BinOp of … extend fun Lang.eval(Plus …) = … }

module B uses Lang = {

abstract class BinOp

extends Lang.Expr of … }

module Comm uses B, Lang = { abstract class BinOp extends B.BinOp of … }

Page 20: Parameterized Modules for Classes and Extensible Functions

20

Enriched class relationsC · C' subtypingC < C' strict subtypingC <k C' k-level subtyping

C <1 C' ´ C extends C'C <0 C' ´ C = C'

C C' non-aliasingC disjoint C' non-intersectionfresh C freshly declared class

Page 21: Parameterized Modules for Classes and Extensible Functions

21

Why these relations?

• Languages with symmetric-best-match dispatch care about inequalities and non-intersection (which is unusual)

• How does one prove methods unambiguous?

fun f:C ! Unitextend fun f(C) = ()extend fun f(D) = ()

– C Å D is non-empty, computable, and covered by a case of f (requires ·)

– D < C– C disjoint D

Page 22: Parameterized Modules for Classes and Extensible Functions

22

Deriving disjointness

C D

A<k <k

C Ddisjoint

Page 23: Parameterized Modules for Classes and Extensible Functions

23

Deriving distinctness

module C = { class Const extends Lang.Expr … }

module N = { class Neg extends Lang.Expr … }

: sig { class Const …

where Const <1 Lang.Expr }

sig { class Neg of {…}

where Neg <1 Lang.Expr }

:

module X = (A:sig { class Neg where Neg disjoint C.Const, … }) = …

fresh Const fresh Neg

• How to modularly deduce non-aliasing?

module NBad = { alias class Neg = C.Const … }

Page 24: Parameterized Modules for Classes and Extensible Functions

24

Enriched class relationsC · C' subtypingC < C' strict subtypingC <k C' k-level subtyping

C <1 C' ´ C extends C'C <0 C' ´ C = C'

C C' non-aliasingC disjoint C' non-intersectionfresh C freshly declared class

Page 25: Parameterized Modules for Classes and Extensible Functions

25

Outline

• Desiderata• Signatures: key issues• Solutions

– Enriched relations– Sealing for subsumption

• Conclusions

Page 26: Parameterized Modules for Classes and Extensible Functions

26

module M = { fun f:(Object, Object) ! Unit extend fun f(Object, Object) =

() extend fun f(Object, Int) = () }

module M = { fun f:(Object, Object) ! Unit extend fun f(Object, Object) =

() extend fun f(Object, Int) = () }

Hiding methods:naïve width subtyping fails

sig { fun f:(Object, Object) ! Unit extend fun f(Object, Object) extend fun f(Object, Int) }

: signature S = sig { fun f:(Object, Object) ! Unit }·

?

module BreakMS = (A:S) ! { class E extends Object extend fun A.f(E, Object) = () }

module Bad = BreakMS(M)

(Object, Object)

(Object, Int)

(Bad.E, Object)

(Bad.E, Int)

module Bad = BreakMS(M) (* { class E extends Object extend fun M.f(E, Object) = () } *)

Page 27: Parameterized Modules for Classes and Extensible Functions

27

What's going on?

• A signature's visible parts give clients bothcapabilities to extend, andobligations they incur by so extending

• Must never hide an obligation while granting the associated capability…

Page 28: Parameterized Modules for Classes and Extensible Functions

28

module M = { fun f:(#Object, Object) ! Unit extend fun f(Object _, Object _) = () extend fun f(Object _, Int _) = () }

What's going on?

sig { fun f:(Object, Object) ! Unit extend fun f(Object, Object) extend fun f(Object, Int) }

: signature S = sig { fun f:(Object, Object) ! Unit }·

?

module BreakMS = (A:S) ! { class E extends Object extend fun A.f(E, Object) = () }

module M = { fun f:(Object, Object) ! Unit extend fun f(Object, Object) =

() extend fun f(Object, Int) = () }

module Bad = BreakMS(M)

(Object, Object)

(Object, Int)

(Bad.E, Object)

(Bad.E, Int)

module Bad = BreakMS(M) (* { class E extends Object extend fun M.f(E, Object) = () } *)

Cannot allow both hiding here…

…and extension here

Page 29: Parameterized Modules for Classes and Extensible Functions

29

supertypes of open below type:

cases may be hidden here

strict subtypes of open below

type: clients may add cases

here

open belowsig { fun f:(Object, Object) ! Unit open below (Object, Object) extend fun f(Object, Object) extend fun f(Object, Int) }

(Object, Object)

(Object, Int)

(Bad.E, Object)

(Bad.E, Int)

sig { fun f:(Object, Object) ! Unit open below (Object, Object)

extend fun f(Object, Int) }

·

Page 30: Parameterized Modules for Classes and Extensible Functions

30

open below

(Object, Object)

(Object, Int)

(Bad.E, Object)

(Bad.E, Int)

supertypes of open below type:

cases may be hidden here

strict subtypes of open below

type: clients may add cases

here

sig { fun f:(Object, Object) ! Unit open below (Object,

Object) }·

sig { fun f:(Object, Object) ! Unit open below (Object, Object) extend fun f(Object, Object) extend fun f(Object, Int) }

Page 31: Parameterized Modules for Classes and Extensible Functions

31

types disjoint from open below type: cases may

be hidden here

open below

(Object, Object)

(Object, Int)

(Bad.E, Object)

(Bad.E, Int)

strict subtypes of open below

type: clients may add cases

here

supertypes of open below type:

cases may be hidden here

sig { fun f:(Object, Object) ! Unit open below (Object,

Int) }·

(Object, String)

sig { fun f:(Object, Object) ! Unit open below (Object, Int) extend fun f(Object, Object) extend fun f(Object, Int) }

sig { fun f:(Object, Object) ! Unit open below (Object, Int) extend fun f(Object, Object) extend fun f(Object, Int) extend fun f(Object, String) }

Page 32: Parameterized Modules for Classes and Extensible Functions

32

open below

(Object, Object)

(Object, Int)

(Bad.E, Object)

(Bad.E, Int)

sig { fun f:(Object, Object) ! Unit open below (Object, Int) }·

sig { fun f:(Object, Object) ! Unit open below (Object, Int) extend fun f(Object, Object) extend fun f(Object, Int) }

sig { fun f:(Object, Object) ! Unit open below (Object,

Object) }

any client that extends below

(Object, Int) also extends below

(Object, Object)

Page 33: Parameterized Modules for Classes and Extensible Functions

33

Hiding functions

• Unsafe to hide an abstract function, and permit concrete extension of class on which that function is abstract

• Class sigs can be closed:closed class C …

denotes class that cannot be extended via this signature

• Abstract functions can only be hidden when "owning" class is closed (& non-instantiable)

Page 34: Parameterized Modules for Classes and Extensible Functions

34

Outline

• Desiderata• Signatures: key issues• Solutions• Conclusions

Page 35: Parameterized Modules for Classes and Extensible Functions

35

Status

• Implementation– Prototype interpreter: handles our examples

• Formalization– Small-step operational semantics– Partial soundness proof (via translation to

EML)– Summary in paper; details/full proof in

technical report (forthcoming) and dissertation (forthcoming, somewhat later)

Page 36: Parameterized Modules for Classes and Extensible Functions

36

Conclusions

• F(EML) combines extensibility, code reuse, and modular typechecking; key features:– Aliases for renaming/remodularization– Rich language of declaration/type relations– Signature subsumption via selective sealing

• Future work:– Hierarchical checking of modularity obligations for

nested modules (relaxed checking)– Multiple dispatch + virtual types + (mutual) recursion