What is a recursive module? Crary, Harper, Puri Module Systems, Fall 2002 Aleksey Kliger.

Slides:



Advertisements
Similar presentations
Types and Programming Languages Lecture 13 Simon Gay Department of Computing Science University of Glasgow 2006/07.
Advertisements

More ML Compiling Techniques David Walker. Today More data structures lists More functions More modules.
Type Checking, Inference, & Elaboration CS153: Compilers Greg Morrisett.
Cs776 (Prasad)L4Poly1 Polymorphic Type System. cs776 (Prasad)L4Poly2 Goals Allow expression of “for all types T” fun I x = x I : ’a -> ’a Allow expression.
1 PROPERTIES OF A TYPE ABSTRACT INTERPRETATER. 2 MOTIVATION OF THE EXPERIMENT § a well understood case l type inference in functional programming à la.
1 Mooly Sagiv and Greta Yorsh School of Computer Science Tel-Aviv University Modern Compiler Design.
Recap 1.Programmer enters expression 2.ML checks if expression is “well-typed” Using a precise set of rules, ML tries to find a unique type for the expression.
8. Introduction to Denotational Semantics. © O. Nierstrasz PS — Denotational Semantics 8.2 Roadmap Overview:  Syntax and Semantics  Semantics of Expressions.
CSE341: Programming Languages Lecture 16 Datatype-Style Programming With Lists or Structs Dan Grossman Winter 2013.
Getting started with ML ML is a functional programming language. ML is statically typed: The types of literals, values, expressions and functions in a.
ML: a quasi-functional language with strong typing Conventional syntax: - val x = 5; (*user input *) val x = 5: int (*system response*) - fun len lis =
Patterns in ML functions. Formal vs. actual parameters Here's a function definition (in C): –int add (int x, int y) { return x + y; } –x and y are the.
INF 212 ANALYSIS OF PROG. LANGS Type Systems Instructors: Crista Lopes Copyright © Instructors.
Cs784(TK)1 Semantics of Procedures and Scopes. Kinds of Scope Static or Lexical scope –determined by structure of program –Scheme, C++, Java, and many.
Module Language. Module language The Standard ML module language comprises the mechanisms for structuring programs into separate units. –Program units.
ML Exceptions.1 Standard ML Exceptions. ML Exceptions.2 Exceptions – The Need  An extensive part of the code is error handling  A function can return.
A Type System for Well-Founded Recursion Derek Dreyer Carnegie Mellon University POPL 2004 Venice, Italy.
Typed Compilation of Recursive Datatypes Joseph C. Vanderwaart, Derek Dreyer, Leaf Petersen, Karl Crary, Robert Harper, and Perry Cheng Carnegie Mellon.
Fall Semantics Juan Carlos Guzmán CS 3123 Programming Languages Concepts Southern Polytechnic State University.
Principal Type Schemes for Modular Programs Derek Dreyer and Matthias Blume Toyota Technological Institute at Chicago ESOP 2007 Braga, Portugal.
Foundations of Programming Languages: Introduction to Lambda Calculus
Data Abstraction COS 441 Princeton University Fall 2004.
ML: a quasi-functional language with strong typing Conventional syntax: - val x = 5; (*user input *) val x = 5: int (*system response*) - fun len lis =
01/17/20031 Guarded Recursive Datatype Constructors Hongwei Xi and Chiyan Chen and Gang Chen Boston University.
Twelf: The Quintessential Proof Assistant for Language Metatheory Karl Crary Carnegie Mellon University Joint work with Robert Harper and Michael Ashley-Rollman.
Elaboration or: Semantic Analysis Compiler Baojian Hua
Introduction to ML Last time: Basics: integers, Booleans, tuples,... simple functions introduction to data types This time, we continue writing an evaluator.
Syntax With Binders COS 441 Princeton University Fall 2004.
Modules in UHC A proposal by: Tom Hofte & Eric Eijkelenboom.
Catriel Beeri Pls/Winter 2004/05 types 65  A type-checking algorithm The task: (since we start with empty H, why is the goal not just E?) The rule set.
Type Inference David Walker COS 441. Criticisms of Typed Languages Types overly constrain functions & data polymorphism makes typed constructs useful.
CSE 130 : Winter 2006 Programming Languages Ranjit Jhala UC San Diego Lecture 7: Polymorphism.
Type Inference David Walker CS 510, Fall Criticisms of Typed Languages Types overly constrain functions & data polymorphism makes typed constructs.
Functional programming: LISP Originally developed for symbolic computing First interactive, interpreted language Dynamic typing: values have types, variables.
Winter 2003/4Pls – syntax – Catriel Beeri1 SYNTAX Syntax: form, structure The syntax of a pl: The set of its well-formed programs The rules that define.
Cs7100(Prasad)L8Proc1 Procedures. cs7100(Prasad)L8Proc2 Primitive procedures  etc User-defined procedures –Naming a sequence of operations.
CSE-321 Programming Languages Introduction to Functional Programming (Part II) POSTECH March 13, 2006 박성우.
Patterns in OCaml functions. Formal vs. actual parameters Here's a function definition (in C): –int add (int x, int y) { return x + y; } –x and y are.
Formal Semantics Chapter Twenty-ThreeModern Programming Languages, 2nd ed.1.
Chapter 9: Functional Programming in a Typed Language.
Functional Programming With examples in F#. Pure Functional Programming Functional programming involves evaluating expressions rather than executing commands.
© Kenneth C. Louden, Chapter 11 - Functional Programming, Part III: Theory Programming Languages: Principles and Practice, 2nd Ed. Kenneth C. Louden.
1 Formal Semantics. 2 Why formalize? ML is tricky, particularly in corner cases generalizable type variables? polymorphic references? exceptions? Some.
Singleton Kinds and Singleton Types Christopher A. Stone August 2, 1999 Thesis Committee Bob Harper, chair Peter Lee John Reynolds Jon Riecke (Bell Laboratories)
Implementing a Dependently Typed λ -Calculus Ali Assaf Abbie Desrosiers Alexandre Tomberg.
12/9/20151 Programming Languages and Compilers (CS 421) Elsa L Gunter 2112 SC, UIUC Based in part on slides by Mattox.
CMSC 330: Organization of Programming Languages Operational Semantics a.k.a. “WTF is Project 4, Part 3?”
A Type System for Higher-Order Modules Derek Dreyer, Karl Crary, and Robert Harper Carnegie Mellon University POPL 2003.
Fall 2008Programming Development Techniques 1 Topic 17 Assignment, Local State, and the Environment Model of Evaluation Section 3.1 & 3.2.
Advanced Functional Programming Tim Sheard 1 Lecture 17 Advanced Functional Programming Tim Sheard Oregon Graduate Institute of Science & Technology Lecture:
CSE 130 : Spring 2011 Programming Languages Ranjit Jhala UC San Diego Lecture 5: Functions and Closures.
CS412/413 Introduction to Compilers Radu Rugina Lecture 13 : Static Semantics 18 Feb 02.
CSE-321 Programming Languages (So Many Topics) POSTECH May 29, 2006 박성우.
CMSC 330: Organization of Programming Languages Operational Semantics.
COMP 412, FALL Type Systems C OMP 412 Rice University Houston, Texas Fall 2000 Copyright 2000, Robert Cartwright, all rights reserved. Students.
Copyright © 2002 Pearson Education, Inc. Slide 1.
Copyright © 2002 Pearson Education, Inc. Slide 1.
Programming Languages and Compilers (CS 421)
ML: a quasi-functional language with strong typing
CSE341: Programming Languages Lecture 16 Datatype-Style Programming With Lists or Structs Dan Grossman Spring 2013.
CSE341: Programming Languages Lecture 16 Datatype-Style Programming With Lists or Structs Zach Tatlock Winter 2018.
CSE341: Programming Languages Lecture 16 Datatype-Style Programming With Lists or Structs Dan Grossman Spring 2017.
CSE341: Programming Languages Lecture 16 Datatype-Style Programming With Lists or Structs Dan Grossman Autumn 2018.
Lecture 15 (Notes by P. N. Hilfinger and R. Bodik)
CSE341: Programming Languages Lecture 16 Datatype-Style Programming With Lists or Structs Dan Grossman Autumn 2017.
CSE-321 Programming Languages Introduction to Functional Programming
CSE341: Programming Languages Lecture 16 Datatype-Style Programming With Lists or Structs Dan Grossman Spring 2016.
Today’s topics Abstractions Procedural Data
CSE341: Programming Languages Lecture 16 Datatype-Style Programming With Lists or Structs Dan Grossman Spring 2019.
Presentation transcript:

What is a recursive module? Crary, Harper, Puri Module Systems, Fall 2002 Aleksey Kliger

CHP Understand the type theory of recursive modules via a phase-splitting interpretation into a constructor and a term expression Introduce recursively-dependent signatures to accurately reflect sharing of type information in recursive modules

Example Recursive modules are useful for splitting a program into several independent pieces Consider the abstract syntax of a fictional ML compiler –Separate types dec and exp for the declarations and expressions –Mutually recursive datatypes

Example cont'd datatype exp = … | LET of dec * exp | … and dec = … | VAL of identifier * exp | … … fun make_let_val (id, e1, body) = let val d = VAL (id, e1) in LET(d,body) end … Suppose we now wish to separate the expressions and the declarations into separate modules

Example cont'd structure Expr = struct datatype exp = … | LET of Decl.dec * exp | … fun make_let_val (id, e1, body) = let val d = Decl.VAL(id, e1) in LET(d, body) end … end structure Decl = struct datatype dec = … | VAL of identifier * Expr.exp | … … End Fails to typecheck: neither structure can be written after the other one

Example cont'd What we would like is to write something like structure rec Expr = struct … End and Decl = struct … end

Fixpoint modules By analogy to fixpoint at term level: fix(x: .e), introduce a module-level fixpoint: fix(s:S.M) The structure variable s stands for the module being defined As with fixpoints at term level, need to ensure that the fixpoint exists and is unique. (Will return to this)

Opaque Recursive Modules To typecheck recursive module fix(s:S.M) suppose module variable s has signature S, and check that module M does. Opaque in the sense that when checking M the only thing we know about s is that it has signature S.

Opaque Recursive Modules Limitations Problem: knowing only that s has signature S is often not enough: The preceeding definition for List fails to typecheck because we do not know within the body of List that t and List.t are the same type, so cannot typecheck cons signature LIST = sig type t val nil : t val cons : int * t -> t end structure rec List :> LIST = struct datatype t = NIL | CONS of int * List.t val nil = NIL fun cons(n:int, l:t): t = CONS(n,l) end

Opaque Recursive Modules Limitations CHP shows a way to program around this deficiency that sacrifices efficiency: fun cons(n:int, l:t): t = case l of NIL => CONS(n,List.NIL) | CONS(n', l') => CONS(n, List.cons(n', l')) In general such a workaround not possible, instead must give List a more precise signature while typechecking the struct

Recursively-dependent signatures CHP solution is to introduce a signature for List which captures the dependency of t on List.t: The signature given to List depends on a structure. Incidentally, that structure is List itself structure rec List :> sig datatype t = NIL | CONS of int * List.t val nil : t val cons : int * t -> t end = struct (* as before *) end

Recursively-dependent signatures A module M may be given the signature  s.S if M may be given signature S[M/s] If module M can be given the rds  s.S then M also has the signature S[M/s] Back to the List example…

Recursively-dependent signatures We assume List has the rds, and check the struct has the same rds (this is our rule for checking fixpoints) cons is now ok because the type of l (that is, t ) is structurally equivalent to List.t s tructure rec List :> sig datatype t = NIL | CONS of int*List.t val nil : t val cons : int * t -> t end = struct datatype t = NIL | CONS of int*List.t val nil : t val cons (x:int, l:t):t = CONS(x,l) end

Transparency Note that the preceding example typechecked because the datatype t was defined transparently in the rds and we appealed to structural equality CHP formalize this as the formation rule for rds's. An rds  s.S is well-formed iff the type components of S are transparent and S is a well-formed sig, in the context where s:S Appealing to structural equality means we're using "equi-recursive" interpretation of recursive constructors

CHP Core Calculus Like HMM with singleton kinds and fixpoints at the constructor and term level kinds  ::= T | 1 | S(c) |  :  1.  2 |  :  1.  2 constructors c ::=  | ¤ |  : .c | c 1 c 2 | hc 1, c 2 i |  I (c) | 1 | c 1 ! c 2 | c 1 £ c 2 |  : .c types  ::= c |  1 ! Tot  2 |  1 !  2 |  1 £  2 | 8  : .  terms e ::= x | ¤ | x: .e | e 1 e 2 | h e 1,e 2 i |  I (e) |  : .e | e[c] | fix(x: .e) contexts  ::=  |  [  :  ] |  [x:  ] |  [  "  ] |  [x"  ]

Fixpoints Contractiveness condition on formation of recursive constructors to ensure that fixpoints exist and are unique Constructor  : .c is well-formed if it actually "goes somewhere", ie it unfolds to an infinite tree. Formalized with judgment c is contractive with kind , provided that  has kind  and is not contractive

Fixpoints Uniqueness of constructor fixpoint reflected by the bisimilarity rule:

Fixpoints There is a value restriction on fixpoints at the term level (more than restricting fix to lambdas because of phase-splitting considerations) Formalized by judgment which says that e is valuable under the assumption that x is not. Lambda abstractions x: .e are always valuable, moreover if e is always valuable, the lambda is deemed total, and its application is always valuable, if its argument is

CHP Structure Calculus Like HMM structure calculus plus new fixpoint modules and rds's constructors c ::= … | Fst s terms e ::= … | Snd s signatures S ::= [  : ,  ] |  s.S modules M ::= [c,e] | fix(s:S.M) contexts  ::= … |  [s:S] |  [s"S]

Fixpoint formation Fixpoint formation formalized to the judgment

Rds intro and elimination A module M may be given the rds  s.S if –  s.S is well-formed (next slide), –and M : S[M/s]  s.S is a dependent signature, and it depends on M Elimination: if M has the rds  s.S, M also has S[M/s]

Rds formation –Constructor part must be transparent –Any module M that may be given this rds may also be given an opaque signature S with all the recursive references in the static part hidden, and all the recursive references at the term level redirected to the static part –The transparent static part must be contractive where S is [  : ,  [  /Fst s]]

Phase splitting interpretation Like in HMM, we understand fixpoint modules via a simple structure obtained by splitting the fixpoint into a static and a dynamic component To phase-split fix(s:[  : .  ].M), suppose that in the context where s has the given signature, M phase splits into [c(Fst s), e(Fst s, Snd s)], then the fixpoint splits into [  =  : .c(  ), fix(x: , e( ,x))] Take the fixpoint of c, and redirect recursive references to the static part in e to the static part of the phase split module

Phase splitting rds's To phase split an rds  s.S we require that S split into [  :S(c(Fst s):  ),  (Fst s)] (ie, S has transparent type components which may refer to types in s) Then the rds splits into [  :S(  : .c(  ) :  ),  (  )] Note that recursive dependency in the static part is handled using recursive types, but dependency in the dynamic part is not essentially recursive

Avoiding static-on-static dependency We can get the Expr/Decl example to work without rds's using only fixpoint modules if we're willing to incur a function call overhead Consider the following opaque signatures: signature DECL = sig type exp type dec val mk_val : identifier * exp -> dec end signature EXPR = sig type exp type dec val mk_let_val : identifier * exp * exp -> exp end

Avoiding static-on-static dependency (cont'd) Structure rec Expr :> EXPR = struct datatype exp = … | LET of Decl.dec * exp | … type dec = Decl.dec fun mk_let_val (id, e1 : exp, body : exp) : exp = let val d = Decl.mk_val(id,e1) in LET(d,body) end … End And Decl :> DECL = struct type exp = Expr.exp datatype dec = … | VAL of identifier * Expr.exp | … fun mk_val (id, e : exp) : dec = VAL(id, e) … end

Practical typechecking To typecheck structure rec A : ASIG(A) = struct … end we would like to –first check that  s.ASIG(s) is well-formed, –then check that the struct has ASIG(A), given that A does. The second step is different from what we said before: to typecheck the fixpoint struct, see if it has type  s.ASIG(s), given that A has  s.ASIG(s) Would like to show that the more direct typechecking strategy is equivalent to the type theoretic method

Practical typechecking cont'd By the intro and elim rules for rds's, A : ASIG(A) iff A :  s. ASIG(s) Would like to know that ASIG(s) and  s.ASIG(s) are eqiuvalent in the context where s has  s.ASIG(s)

Practical typechecking cont'd Given s : \rho s. ASIG(s) ASIG(s) = [  :S(c(Fst s):  ),  (Fst s)](by well-formedness of  s.ASIG(s)) = [  : S(c(  : .c(  )):  ),  (  : .c(  ))](by phase-splitting s's sig) = [  : S(  : .c(  ):  ),  (  : .c(  ))](by roll up and singleton kinds) = [  : S(  : .c(  ):  ),  (  )](by singleton kinds and structures) =  s.ASIG(s)(by phase splitting) (for appropriate c, , 

Practical typechecking cont'd Typechecking still critically depends on equality of equi-recursive constructors at higher kind Hard problem, maybe reducible to equivalence problem of DPDAs which is decidable but no practical (efficient) algorithm

Iso-recursive types Type equality for equirecursive types is hard Would rather use iso-recursive types Compiling datatypes typically use iso- recursive types anyway Seems like "most of the time" recursive modules have static-on-static dependencies are within datatypes

Iso-recursive types Turns out need to adopt Shao's equation to compile recursive modules using iso-recursive types Let   .c(  ) be the iso-recursive type. Then Shao's equation says   .c(  ) =      )))

Iso-recursive types If restrict the type components of an rds to only being datatypes, then after phase- splitting, the static part of an rds will be of the form .   .c( ,  ) By invoking Shao's equation and bisimilarity, can show this is equivalent to   .c( ,  ) Ie, uses of equi-recursive types may be eliminated

Conclusion Phase splitting interpretation of opaque fixpoint modules and transparent rds's Rds's are a novel way of formalizing the type theory of recursive modules Relies on equi-recursive types Not clear if this is a practical language to typecheck

Other approaches Derek R. Dreyer, Robert Harper, and Karl Crary. Toward a Practical Type Theory for Recursive Modules. There appear to be several different ways of typechecking fixpoint modules which admit more examples, by considering the use of recursive types in the phase splitting interpretation of fixpoint modules I did not really understand this TR