An Introduction to Nominal Sets Andrew Pi t s Computer Science & Technology EWSCS 2020 1/70
Lecture 4 52/70
Outline L1 Structural recursion and induction in the presence of name-binding operations. L2 Introducing the category of nominal sets. L3 Nominal algebraic data types and 훼 -structural recursion. L4 Dependently typed 휆 -calculus with locally fresh names and name-abstraction. References: AMP, Nominal Sets: Names and Symmetry in Computer Science , CUP 2013 AMP, Alpha-Structural Recursion and Induction , JACM 53(2006)459-506. AMP, J. Ma t hiesen and J. Derikx, A Dependent Type Theory with Abstractable Names , ENTCS 312(2015)19-50. 53/70
Original motivation for Gabbay & AMP to introduce nominal sets and name abstraction: [ A ]( ) can be combined with × and + to give functors Nom → Nom that have initial algebras coinciding with sets of abstract syntax trees modulo 훼 -equivalence. E.g. the initial algebra for A + ( × ) + [ A ]( ) is isomorphic to the usual set of untyped 휆 -terms. 54/70
Recall: 훼 -Structural recursion For 휆 -terms: Theorem. 푓 1 ∈ A � fs 푋 Given any 푋 ∈ Nom and ∈ 푋 × 푋 � fs 푋 s.t. 푓 2 ∈ A × 푋 � fs 푋 푓 3 N (FCB) 푎 , ∀ 푥 , 푎 # 푓 3 ( 푎 , 푥 ) ˆ ∃ ! ˆ 푓 푎 = 푓 1 푎 푓 ∈ Λ � fs 푋 푓 ( 푒 1 푒 2 ) = 푓 2 ( ˆ ˆ 푓 푒 1 , ˆ s.t. 푓 푒 2 ) 푓 ( 휆푎 . 푒 ) = 푓 3 ( 푎 , ˆ ˆ if 푎 # ( 푓 1 , 푓 2 , 푓 3 ) 푓 푒 ) Can we avoid explicit reasoning about finite support, # and (FCB) when computing ‘mod 훼 ’? Want definition/computation to be separate from proving. 55/70
ˆ 푓 = 푓 1 푎 푓 ( 푒 1 푒 2 ) = 푓 2 ( ˆ ˆ 푓 푒 1 , ˆ 푓 푒 2 ) ˆ 푓 3 ( 푎 , ˆ if 푎 # ( 푓 1 , 푓 2 , 푓 2 ) 푓 ( 휆푎 . 푒 ) = 푓 푒 ) = 푓 3 ( 푎 ′ , ˆ = 휆푎 ′ . 푒 ′ 푓 푒 ′ ) Q: how to get rid of this inconvenient proof obligation? 56/70
ˆ 푓 = 푓 1 푎 푓 ( 푒 1 푒 2 ) = 푓 2 ( ˆ ˆ 푓 푒 1 , ˆ 푓 푒 2 ) 푓 ( 휆푎 . 푒 ) = 휈푎 . 푓 3 ( 푎 , ˆ ˆ 푓 푒 ) [ 푎 # ( 푓 1 , 푓 2 , 푓 2 ) ] = 휈푎 ′ . 푓 3 ( 푎 ′ , ˆ = 휆푎 ′ . 푒 ′ 푓 푒 ′ ) 푂퐾 ! Q: how to get rid of this inconvenient proof obligation? A: use a local scoping construct 휈푎 . ( − ) for names 56/70
ˆ 푓 = 푓 1 푎 푓 ( 푒 1 푒 2 ) = 푓 2 ( ˆ ˆ 푓 푒 1 , ˆ 푓 푒 2 ) 푓 ( 휆푎 . 푒 ) = 휈푎 . 푓 3 ( 푎 , ˆ ˆ 푓 푒 ) [ 푎 # ( 푓 1 , 푓 2 , 푓 2 ) ] = 휈푎 ′ . 푓 3 ( 푎 ′ , ˆ = 휆푎 ′ . 푒 ′ 푓 푒 ′ ) 푂퐾 ! Q: how to get rid of this inconvenient proof obligation? A: use a local scoping construct 휈푎 . ( − ) for names which one ? 56/70
Dynamic allocation ◮ Stateful: 휈푎 . 푡 means “add a fresh name 푎 ′ to the current state and return 푡 [ 푎 ′ / 푎 ] ”. ◮ Used in Shinwell’s Fresh OCaml = OCaml + ◮ name types and name-abstraction type former ◮ name-abstraction pa t erns —matching involves dynamic allocation of fresh names [MR Shinwell, AMP, MJ Gabbay, FreshML: Programming with Binders Made Simple , Proc. ICFP 2003.] [ www.cl.cam.ac.uk/users/amp12/fresh-ocaml ] 57/70
Sample Fresh OCaml code (* syntax *) type t;; type var = t name;; type term = Var of var | Lam of <<var>>term | App of term*term;; (* semantics *) type sem = L of ((unit -> sem) -> sem) | N of neu and neu = V of var | A of neu*sem;; (* reify : sem -> term *) let rec reify d = match d with L f -> let x = fresh in Lam(<<x>>(reify(f(function () -> N(V x))))) | N n -> reifyn n and reifyn n = match n with V x -> Var x | A(n’,d’) -> App(reifyn n’, reify d’);; (* evals : (var * (unit -> sem))list -> term -> sem *) let rec evals env t = match t with Var x -> (match env with [] -> N(V x) | (x’,v)::env -> if x=x’ then v() else evals env (Var x)) | Lam(<<x>>t) -> L(function v -> evals ((x,v)::env) t) | App(t1,t2) -> (match evals env t1 with L f -> f(function () -> evals env t2) | N n -> N(A(n,evals env t2)));; (* eval : term -> sem *) let rec eval t = evals [] t;; (* norm : lam -> lam *) let norm t = reify(eval t);; 58/70
Dynamic allocation ◮ Stateful: 휈푎 . 푡 means “add a fresh name 푎 ′ to the current state and return 푡 [ 푎 ′ / 푎 ] ”. ◮ Used in Shinwell’s Fresh OCaml = OCaml + ◮ name types and name-abstraction type former ◮ name-abstraction pa t erns —matching involves dynamic allocation of fresh names [MR Shinwell, AMP, MJ Gabbay, FreshML: Programming with Binders Made Simple , Proc. ICFP 2003.] [ www.cl.cam.ac.uk/users/amp12/fresh-ocaml ] 59/70
Dynamic allocation ◮ Stateful: 휈푎 . 푡 means “add a fresh name 푎 ′ to the current state and return 푡 [ 푎 ′ / 푎 ] ”. Statefulness disrupts familiar mathematical properties of pure datatypes. So let’s try to reject it in favour of... 59/70
Aim A version of Martin-L¨ of Type Theory enriched with constructs for locally fresh names and name-abstraction from the theory of nominal sets. Motivation: Machine-assisted construction of humanly understandable formal proofs about so f ware (PL semantics). 60/70
Aim More specifically: extend (dependently typed) 휆 -calculus with names 푎 name swapping swap 푎 , 푏 in 푡 name abstraction � 푎 � 푡 and concretion 푡 @ 푎 locally fresh names fresh 푎 in 푡 name equality if 푡 = 푎 then 푡 1 else 푡 2 61/70
Locally fresh names For example, here are some isomorphisms, described in an informal pseudocode: 푖 : [ A ]( 푋 + 푌 ) � [ A ] 푋 + [ A ] 푌 푖 ( 푧 ) = fresh 푎 in case 푧 @ 푎 of inl ( 푥 ) � � 푎 � 푥 | inr ( 푦 ) � � 푎 � 푦 [Ex. 7] 62/70
Locally fresh names For example, here are some isomorphisms, described in an informal pseudocode: 푖 : [ A ]( 푋 + 푌 ) � [ A ] 푋 + [ A ] 푌 푖 ( 푧 ) = fresh 푎 in case 푧 @ 푎 of inl ( 푥 ) � � 푎 � 푥 | inr ( 푦 ) � � 푎 � 푦 given 푓 ∈ Nom ( 푋 ∗ A , 푌 ) satisfying 푎 # 푥 ⇒ 푎 # 푓 ( 푥 , 푎 ) , we get ˆ 푓 ∈ Nom ( 푋 , 푌 ) well-defined by: ˆ 푓 ( 푥 ) = 푓 ( 푥 , 푎 ) for some/any 푎 # 푥 . Notation: fresh 푎 in 푓 ( 푥 , 푎 ) � ˆ 푓 ( 푥 ) 62/70
Locally fresh names For example, here are some isomorphisms, described in an informal pseudocode: 푖 : [ A ]( 푋 + 푌 ) � [ A ] 푋 + [ A ] 푌 푖 ( 푧 ) = fresh 푎 in case 푧 @ 푎 of inl ( 푥 ) � � 푎 � 푥 | inr ( 푦 ) � � 푎 � 푦 푗 : ([ A ] 푋 � fs [ A ] 푌 ) � [ A ]( 푋 � fs 푌 ) 푗 ( 푓 ) = fresh 푎 in � 푎 � ( 휆푥 . 푓 ( � 푎 � 푥 ) @ 푎 ) Can one turn the pseudocode into terms in a formal ‘nominal’ 휆 -calculus? 62/70
Prior art ◮ Stark-Sch¨ opp [CSL 2004] bunched contexts ( + ), extensional & undecidable ( − ) ◮ Westbrook-Stump-Austin [LFMTP 2009] CNIC semantics/expressivity? ◮ Cheney [LMCS 2012] DNTT bunched contexts ( + ), no local fresh names ( − ) ◮ Fairweather-Fern´ andez-Szasz-Tasistro [2012] based on nominal terms ( + ), explicit substitutions ( − ), first-order ( ± ) ◮ Crole-Nebel [MFPS 2013] simple types ( − ), definitional freshness ( + ) 63/70
Our art ◮ Stark-Sch¨ opp [CSL 2004] bunched contexts ( + ), extensional & undecidable ( − ) ◮ Westbrook-Stump-Austin [LFMTP 2009] CNIC semantics/expressivity? ◮ Cheney [LMCS 2012] DNTT bunched contexts ( + ), no local fresh names ( − ) ◮ Fairweather-Fern´ andez-Szasz-Tasistro [2012] based on nominal terms ( + ), explicit substitutions ( − ), first-order ( ± ) ◮ Crole-Nebel [MFPS 2013] simple types ( − ), definitional freshness ( + ) AMP, J. Ma t hiesen and J. Derikx, A Dependent Type Theory with Abstractable Names , ENTCS 312(2015)19-50. 63/70
Aim More specifically: extend (dependently typed) 휆 -calculus with names 푎 name swapping swap 푎 , 푏 in 푡 name abstraction � 푎 � 푡 and concretion 푡 @ 푎 locally fresh names fresh 푎 in 푡 name equality if 푡 = 푎 then 푡 1 else 푡 2 Di ff iculty: concretion and locally fresh names are partially defined – have to check freshness conditions. e.g. for fresh 푎 in 푓 ( 푥 , 푎 ) to be well-defined, we need 푎 # 푥 ⇒ 푎 # 푓 ( 푥 , 푎 ) 64/70
Definitional freshness In a nominal set of (higher-order) functions, proving 푎 # 푓 can be tricky (undecidable). Common proof pa t ern: Given 푎 , 푓 , . . . , pick a fresh name 푏 and prove ( 푎 푏 ) · 푓 = 푓 . (For functions, equivalent to prov- ing ∀ 푥 , ( 푎 푏 ) · 푓 ( 푥 ) = 푓 (( 푎 푏 ) · 푥 ) .) 65/70
Definitional freshness In a nominal set of (higher-order) functions, proving 푎 # 푓 can be tricky (undecidable). Common proof pa t ern: Given 푎 , 푓 , . . . , pick a fresh name 푏 and prove ( 푎 푏 ) · 푓 = 푓 . Since by choice of 푏 we have 푏 # 푓 , we also get 푎 = ( 푎 푏 ) · 푏 # ( 푎 푏 ) · 푓 = 푓 , QED. 65/70
Definitional freshness Γ ⊢ 푎 # 푇 Γ ⊢ 푡 : 푇 Γ # ( 푏 : A ) ⊢ ( swap 푎 , 푏 in 푡 ) = 푡 : 푇 Γ ⊢ 푎 # 푡 : 푇 bunched contexts, generated by definitional definitional ↦→ Γ ( 푥 : 푇 ) Γ equality freshness ↦→ Γ # ( 푎 : A ) Γ 65/70
Recommend
More recommend