
Arity-Generic Datatype-Generic Programming Chris Casinghino Stephanie Weirich University of Pennsylvania January 19, 2010 PLPV, Madrid 1/32 Outline 1 Motivation 2 Arities in Datatype-Generic Programming 3 A Universe for Generic Programming 4 The Framework 5 Arity-Generic Map 6 Conclusion 2/32 Datatype-Genericity Datatype-generic functions can be implemented for many datatypes. list-map :(a ! b) ! [a] ! [b] maybe-map :(a ! b) ! Maybea ! Maybeb pair-map :(a1 ! a2) ! (b1 ! b2) ! (a1; b1) ! (a2; b2) 3/32 Arity-Genericity Arity-generic functions can be implemented at many arities. At higher arities, map is often called zip. The Haskell standard library includes: repeat : a ! [a] map :(a ! b) ! [a] ! [b] zipWith :(a ! b ! c) ! [a] ! [b] ! [c] zipWith3 :(a ! b ! c ! d) ! [a] ! [b] ! [c] ! [d] 4/32 Doubly Generic Functions • Some functions, like map, are doubly generic. pair-map1 : a1 ! a2 ! (a1; a2) maybe-map2 :(a ! b) ! Maybea ! Maybeb list-map3 :(a ! b ! c) ! [a] ! [b] ! [c] ... • Goal: one function, ngmap, which produces any of these denitions from an arity and a type. For example: ngmap2 Maybe :(a ! b) ! Maybea ! Maybeb • Importantly, the notion of arity already appears in datatype-generic programming (but not arity-genericity). 5/32 Motivation Why study doubly generic functions? • They can reduce boilerplate. • We may be able to prove properties generally for all instances of doubly generic functions. • New insight into the nature of operations like map. • Formally specifying a framework for them helps us nd more. 6/32 Outline 1 Motivation 2 Arities in Datatype-Generic Programming 3 A Universe for Generic Programming 4 The Framework 5 Arity-Generic Map 6 Conclusion 7/32 Dierent Types at Dierent Kinds • Consider equality functions for various types: nat-eq : N ! N ! Bool list-eq : 8 a : (a ! a ! Bool) ! [a] ! [a] ! Bool pair-eq : 8 ab : (a ! a ! Bool) ! (b ! b ! Bool) ! (a; b) ! (a; b) ! Bool • Generic Haskell style datatype-generic programs have kind-indexed types. Eq h?i t = t ! t ! Bool Eq hk1 ) k2i t = 8 a : Eq hk1i a ! Eq hk2i (ta ) • The kind-indexed type Eq has arity one, because it takes one type argument. 8/32 Kind-indexed Types for Maps • On the other hand, datatype-generic map has a kind-indexed type of arity two. Map h?i t1 t2 = t1 ! t2 Map hk1 ) k2i t1 t2 = 8 ab : Map hk1i ab ! Map hk2i (t1 a)(t2 b) • Datatype-generic zipWith has a kind-indexed type of arity three. Zip h?i t1 t2 t3 = t1 ! t2 ! t3 Zip hk1 ) k2i t1 t2 t3 = 8 abc : Zip hk1i abc ! Zip hk2i (t1 a)(t2 b)(t3 c) • These two look very similar... 9/32 Summary • Arities already show up in standard kind-indexed types. • Some frameworks for datatype-generic programming support dierent arities (but not generalizing over the arity). • New observation: when written in dependently-typed languages, they can support arity-genericity too. 10/32 Outline 1 Motivation 2 Arities in Datatype-Generic Programming 3 A Universe for Generic Programming 4 The Framework 5 Arity-Generic Map 6 Conclusion 11/32 Universes • In dependently typed languages (like Agda), generic programming frameworks are implemented using universes. • A universe is: • A data structure to represent part of the type language • And an interpretation function to convert members of the datatype to actual Agda types. • A generic program is dened by recursion over the universe. • Our universe is based on the type language of F !it's essentially STLC. 12/32 Kinds • We dene a data type to represent kinds, and a function to interpret its members (the codes) as Agda kinds. data Kind : Set where ? : Kind _)_ : Kind ! Kind ! Kind _ : Kind ! Set J ?K = Set J a )K b = a ! b J K J K J K • Set is the classier of Agda types. We'll gloss over some details of the type hierarchy. 13/32 Type Constants Type constants are indexed by their kinds. data Const : Kind ! Set where Unit : Const ? Nat : Const ? Sum : Const (? ) ? ) ?) Prod : Const (? ) ? ) ?) interp-c : 8f kg! Constk ! k interp-c Unit = > J K interp-c Nat = N interp-c Sum = _]_ interp-c Prod = _×_ 14/32 Types • Types comprise variables, functions, applications, and constants. data Ty : Ctx ! Kind ! Set where Var : ... Lam : ... App : ... Con : ... • We have a function for interpreting closed Types: b_c : 8f kg! Ty [] k ! k J K 15/32 Example • As an example, we might dene an Option type in Agda, isomorphic to the standard datatype: Option : Set ! Set Option = λ A !>] A • We can represent it with a code: option : Ty [](? ) ?) option = Lam (App (App (Con Sum)(Con Unit)) (VarVZ )) • Agda can see that b option c normalizes to Option. 16/32 Outline 1 Motivation 2 Arities in Datatype-Generic Programming 3 A Universe for Generic Programming 4 The Framework 5 Arity-Generic Map 6 Conclusion 17/32 Preliminaries • We need just two more things. • Agda's library has length indexed vectors: data Vec (A : Set): N ! Set where []: VecA zero _::_ : 8f ng (a : A)(xs : VecAn ) ! VecA (sucn ) • We dene_ ~_, pronounced zap, a zipping application on vectors: _~_ : fAB : Setg fn : Ng ! Vec (A ! B) n ! VecAn ! VecBn • And repeat, which createsn copies of a term: repeat : fA : Setg! (n : N) ! A ! VecAn 18/32 Kind-indexed Types revisited • Observe that the kind-indexed types we saw before have a very regular form: Eq h?i t = t ! t ! Bool Eq hk1 ) k2i t = 8 a : Eq hk1i a ! Eq hk2i (ta ) Map h?i t1 t2 = t1 ! t2 Map hk1 ) k2i t1 t2 = 8 ab : Map hk1i ab ! Map hk2i (t1 a)(t2 b) • At kind ?, they use the type argument(s) in an operation-specic way. • At arrow kinds they are logical and completely regular. 19/32 Kind-indexed Types, formally • So, we can derive instances of kind-indexed types automatically if provided with the denition at base kinds: _h_i_ : fn : Ng! (b : Vec Setn ! Set) ! (k : Kind) ! Vec k n ! Set J K b h ? i v = bv b h k1 ) k2 i v = (a : Vec k1 ) ! b h k1 i a ! b h k2 i (v ~ a) J K • Since the number of type arguments is variable, we take them as a vector. • In the development, this denition is then curried so users can supply the types individually. 20/32 Example: GMap • Datatype-generic map has arity two. Its base type is: GMap :(v : Vec Set2 ) ! Set GMap (A::B:: [ ]) = A ! B • GMap h? ) ?i (repeat2 List ) normalizes to: 8f AB : Setg! (A ! B) ! ListA ! ListB • GMap h? ) ? ) ?i (repeat2_ ×_) normalizes to: 8f A1 B1 : Setg! (A1 ! B1) !f A2 B2 : Setg! (A2 ! B2) ! (A1 × A2) ! (B1 × B2) 21/32 The Framework • Users implement the operation for type constants by constructing a TyConstEnvb TyConstEnvb = fk : Kindg (c : Constk ) ! b h k i (repeat b Conc c) • Then they call ngen: ngen : fn : Ng fb : Vec Setn ! Setg fk : Kindg ! (TyConstEnvb ) ! (t : Ty [] k) ! b h k i (repeatn b t c) 22/32 Map's TyConstEnv • We've already dened datatype-generic map's type. • Now, its TyConstEnv. gmap-const : TyConstEnv GMap gmap-const Nat = λ x ! x gmap-const Unit = λ x ! x gmap-const Prod = λ f1 f2x ! (f1 (proj1 x); f2 (proj2 x)) gmap-const Sum = g where g : fA1 B1 A2B2 : Setg ! (A1 ! B1) ! (A2 ! B2) ! A1 ] A2 ! B1 ] B2 g fa fb (inj1 xa) = inj1 (fa xa) g fa fb (inj2 xb) = inj2 (fb xb) 23/32 Datatype-Generic Map • With gmap-const, we can dene datatype-generic map: gmap : fk : Kindg! (t : Ty [] k) ! GMap h k i (b t c :: b t c :: [ ]) gmapt = ngen gmap-constt • For example: option-map : fAB : Setg! (A ! B) ! OptionA ! OptionB option-map = gmap option • Using generic functions at actual Agda datatypes is discussed in the paper. 24/32 Outline 1 Motivation 2 Arities in Datatype-Generic Programming 3 A Universe for Generic Programming 4 The Framework 5 Arity-Generic Map 6 Conclusion 25/32 Writing Arity-Generic Programs • All the pieces of the framework are parameterized by arity: _h_i_ : fn : Ng! (b : Vec Setn ! Set) ! (k : Kind) ! Vec k n ! Set J K TyConstEnv : fn : Ng! (b : Vec Setn ! Set) ! Set ngen : fn : Ng fb : Vec Setn ! Setg fk : Kindg ! (TyConstEnvb ) ! (t : Ty [] k) ! b h k i (repeatn b t c)) • So, if we deneb and the TyConstEnv while leaving the arity general, we can get out an arity-generic denition. 26/32 Arity-Generic Map • So, we want to dene arity-generic map's base type and TyConstEnv for any arity: NGmap : fn : Ng! Vec Setn ! Set NGmap Ts = see the paper! ngmap-const : fn : Ng! TyConstEnv fng NGmap ngmap-const fng c = see the paper! • With these, we can get arity-generic map directly from ngen. ngmap : fk : Kindg! (n : N) ! (t : Ty [] k) ! NGmap h k i (repeatn b t c) ngmapnt = ngen ngmap-constt 27/32 Examples with ngmap For example, maps and zips on products are instances of ngmap: pair-map1 : fAB : Setg! A ! B ! A × B pair-map1 = ngmap1 (Con Prod) pair-map2 : fA1 B1 A2B2 : Setg ! (A1 ! B1) ! (A2 ! B2) ! A1 × A2 ! B1 × B2 pair-map2 = ngmap2 (Con Prod) pair-map3 : fA1 B1 C1 A2 B2 C2 : Setg ! (A1 ! B1 ! C1) ! (A2 ! B2 ! C2) ! A1 × A2 ! B1 × B2 ! C1 × C2 pair-map3 = ngmap3 (Con Prod) 28/32 Outline 1 Motivation 2 Arities in Datatype-Generic Programming 3 A Universe for Generic Programming 4 The Framework 5 Arity-Generic Map 6 Conclusion 29/32 Conclusion Also in the paper: • More arity-generic programs (equality, unzip, folds).
Details
-
File Typepdf
-
Upload Time-
-
Content LanguagesEnglish
-
Upload UserAnonymous/Not logged-in
-
File Pages32 Page
-
File Size-