last time gadts
play

Last time: GADTs a b 1/ 48 This time: GADT programming patterns - PowerPoint PPT Presentation

Last time: GADTs a b 1/ 48 This time: GADT programming patterns 2/ 48 Recapitulation 3/ 48 Recapitulation: technical GADT type indexes vary across constructors. We have families of types: a type per nat, per tree depth, etc. GADTs need


  1. Last time: GADTs a ≡ b 1/ 48

  2. This time: GADT programming patterns 2/ 48

  3. Recapitulation 3/ 48

  4. Recapitulation: technical GADT type indexes vary across constructors. We have families of types: a type per nat, per tree depth, etc. GADTs need machinery from earlier lectures: existentials, polymorphic recursion, non-regularity. GADTs are about type equalities (and sometimes inequalities). Type equalities are revealed by examining data. Compilers use the richer types to generate better code. 4/ 48

  5. Recapitulation: philosophical Phantom types protect abstractions against misuse. GADTs also protect definitions. GADTs lead to rich types which can be viewed as propositions. Descriptive data types lead to useful function types. 5/ 48

  6. Equality 6/ 48

  7. Recall: equality in System F ω Eq = λα : : ∗ . λβ : : ∗ . ∀ φ : : ∗ ⇒∗ . φ α → φ β r e f l : ∀ α : : ∗ . Eq α α r e f l = Λ α : : ∗ . Λ φ : : ∗ ⇒∗ . λ x : φ α . x symm : ∀ α : : ∗ . ∀ β : : ∗ . Eq α β → Eq β α symm = Λ α : : ∗ . Λ β : : ∗ . λ e : ( ∀ φ : : ∗ ⇒∗ . φ α → φ β ) . e [ λγ : : ∗ . Eq γ α ] ( r e f l [ α ] ) t r a n s : ∀ α : : ∗ . ∀ β : : ∗ . ∀ γ : : ∗ . Eq α β → Eq β γ → Eq α γ t r a n s = Λ α : : ∗ . Λ β : : ∗ . Λ γ : : ∗ . λ ab : Eq α β . λ bc : Eq β γ . bc [ Eq α ] ab 7/ 48

  8. Equlity with GADTs type ( , ) e q l = R e f l : ( ’ a , ’ a ) e q l r e f l : ( ’ a , ’ a ) e q l val val symm : ( ’ a , ’ b) e q l → ( ’ b , ’ a ) e q l val t r a n s : ( ’ a , ’ b) e q l → ( ’ b , ’ c ) e q l → ( ’ a , ’ c ) e q l module L i f t (T : sig type t end ) : sig l i f t : ( ’ a , ’ b) e q l → ( ’ a T. t , ’ b T. t ) e q l val end val cast : ( ’ a , ’ b) e q l → ’ a → ’b 8/ 48

  9. Building GADTs from algebraic types and equality type ( ’ a , ) g t r e e = EmptyG : ( ’ a , z ) g t r e e | TreeG : ( ’ a , ’ n) g t r e e ∗ ’ a ∗ ( ’ a , ’ n) g t r e e → ( ’ a , ’ n s ) g t r e e type ( ’ a , ’ n) e t r e e = EmptyE : ( z , ’ n) e q l → ( ’ a , ’ n) e t r e e | TreeE : ( ’ n , ’m s ) e q l ∗ ( ’ a , ’m) e t r e e ∗ ’ a ∗ ( ’ a , ’m) e t r e e → ( ’ a , ’ n) e t r e e 9/ 48

  10. Building GADTs from algebraic types and equality type ( ’ a , ) g t r e e = EmptyG : ( ’ a , z ) g t r e e | TreeG : ( ’ a , ’ n) g t r e e ∗ ’ a ∗ ( ’ a , ’ n) g t r e e → ( ’ a , ’ n s ) g t r e e l e t rec depthG : type a n . ( a , n) g t r e e → n = f u n c t i o n EmptyG → Z | TreeG ( l , , ) → S ( depthG l ) 10/ 48

  11. Building GADTs from algebraic types and equality type ( ’ a , ) g t r e e = EmptyG : ( ’ a , z ) g t r e e | TreeG : ( ’ a , ’ n) g t r e e ∗ ’ a ∗ ( ’ a , ’ n) g t r e e → ( ’ a , ’ n s ) g t r e e l e t rec depthG : type a n . ( a , n) g t r e e → n = f u n c t i o n EmptyG → Z (* n = z *) | TreeG ( l , , ) → S ( depthG l ) 10/ 48

  12. Building GADTs from algebraic types and equality type ( ’ a , ) g t r e e = EmptyG : ( ’ a , z ) g t r e e | TreeG : ( ’ a , ’ n) g t r e e ∗ ’ a ∗ ( ’ a , ’ n) g t r e e → ( ’ a , ’ n s ) g t r e e l e t rec depthG : type a n . ( a , n) g t r e e → n = f u n c t i o n EmptyG → Z (* n = z *) | TreeG ( l , , ) → S ( depthG l ) (* n = m s *) 10/ 48

  13. Building GADTs from algebraic types and equality type ( ’ a , ’ n) e t r e e = EmptyE : ( ’ n , z ) e q l → ( ’ a , ’ n) e t r e e | TreeE : ( ’ n , ’m s ) e q l ∗ ( ’ a , ’m) e t r e e ∗ ’ a ∗ ( ’ a , ’m) e t r e e → ( ’ a , ’ n) e t r e e l e t rec depthE : type a n . ( a , n) e t r e e → n = f u n c t i o n EmptyE R e f l → Z | TreeE ( Refl , l , , ) → S ( depthE l ) 11/ 48

  14. Building GADTs from algebraic types and equality type ( ’ a , ’ n) e t r e e = EmptyE : ( ’ n , z ) e q l → ( ’ a , ’ n) e t r e e | TreeE : ( ’ n , ’m s ) e q l ∗ ( ’ a , ’m) e t r e e ∗ ’ a ∗ ( ’ a , ’m) e t r e e → ( ’ a , ’ n) e t r e e l e t rec depthE : type a n . ( a , n) e t r e e → n = f u n c t i o n EmptyE R e f l → Z (* n = z *) | TreeE ( Refl , l , , ) → S ( depthE l ) 11/ 48

  15. Building GADTs from algebraic types and equality type ( ’ a , ’ n) e t r e e = EmptyE : ( ’ n , z ) e q l → ( ’ a , ’ n) e t r e e | TreeE : ( ’ n , ’m s ) e q l ∗ ( ’ a , ’m) e t r e e ∗ ’ a ∗ ( ’ a , ’m) e t r e e → ( ’ a , ’ n) e t r e e l e t rec depthE : type a n . ( a , n) e t r e e → n = f u n c t i o n EmptyE R e f l → Z (* n = z *) | TreeE ( Refl , l , , ) → S ( depthE l ) (* n = m s *) 11/ 48

  16. GADT programming patterns 12/ 48

  17. A new example: representing (some) JSON JSON values json ::= true | f a l s e | string | number | n u l l [ ] | [ json-seq ] {} | { json-kvseq } json-seq ::= json , json-seq json json-kvseq ::= string : json string : json , string : json-kvseq 13/ 48

  18. A new example: representing (some) JSON JSON values json ::= true | f a l s e | string | number | n u l l [ ] | [ json-seq ] json-seq ::= json , json-seq json A JSON value [ ”one ” , true , 3.4 , [ [ ” four ” ] , [ n u l l ] ] ] 14/ 48

  19. An “untyped” JSON representation type ujson = UStr : s t r i n g → ujson | UNum : f l o a t → ujson | UBool : bool → ujson | UNull : ujson | UArr : ujson l i s t → ujson [ ”one ” , true , 3.4 , [ [ ” four ” ] , [ n u l l ] ] ] UArr [ UStr ”one ”; UBool true ; UNum 3 . 4 ; UArr [ UArr [ UStr ” four ” ] ; UArr [ UNull ] ] ] 15/ 48

  20. Pattern : Richly typed data Data may have finer structure than algebraic data types can express. GADT indexes allow us to specify constraints more precisely. 16/ 48

  21. Richly typed data type t j s o n = Str : s t r i n g → s t r i n g t j s o n | Num : f l o a t → f l o a t t j s o n | Bool : bool → bool t j s o n | Null : u n i t t j s o n | Arr : ’ a t a r r → ’ a t j s o n and t a r r = N i l : u n i t t a r r | : : : ’ a t j s o n ∗ ’b t a r r → ( ’ a ∗ ’b) t a r r Arr ( Str ”one” : : Bool true : : Num 3.4 : : Arr ( Arr ( Str ” four ” : : N i l ) : : Null : : N i l ) : : N i l ) 17/ 48

  22. Richly typed data ( ∗ negate a l l the bools in a JSON value ∗ ) l e t rec unegate : ujson → ujson = . . . ( ∗ negate a l l the bools in a JSON value ∗ ) l e t rec negate : type a . a t j s o n → a t j s o n = f u n c t i o n Bool true → Bool f a l s e | Bool f a l s e → Bool true | Arr a r r → Arr ( n e g a t e a r r a r r ) | v → v and n e g a t e a r r : type a . a t a r r → a t a r r = f u n c t i o n N i l → N i l | j : : j s → negate j : : n e g a t e a r r j s 18/ 48

  23. Pattern : Building GADT values It’s not always possible to determine index types statically. For example, the depth of a tree might depend on user input. 19/ 48

  24. Building GADT values: two approaches How might a function make t build a value of a GADT type t ? l e t make t : type a . s t r i n g → a t = . . . 20/ 48

  25. Building GADT values: two approaches How might a function make t build a value of a GADT type t ? l e t make t : type a . s t r i n g → a t = ✗ 20/ 48

  26. Building GADT values: two approaches How might a function make t build a value of a GADT type t ? l e t make t : type a . s t r i n g → a t = ✗ With existentials make t builds a value of type ’a t for some ’a. 20/ 48

  27. Building GADT values: two approaches How might a function make t build a value of a GADT type t ? l e t make t : type a . s t r i n g → a t = ✗ With existentials make t builds a value of type ’a t for some ’a. With universals the caller of make t must accept ’a t for any ’a. 20/ 48

  28. Building GADT values with existentials type e t j s o n = ETJson : ’ a t j s o n → e t j s o n type e t a r r = ETArr : ’ a t a r r → e t a r r l e t rec t j s o n o f u j s o n : ujson → e t j s o n = f u n c t i o n UStr s → ETJson ( Str s ) | UNum u → ETJson (Num u) | UBool b → ETJson ( Bool b) | UNull → ETJson Null | UArr a r r → l e t ETArr arr ’ = t a r r o f u a r r a r r in ETJson ( Arr arr ’ ) and t a r r o f u a r r : ujson l i s t → e t a r r = f u n c t i o n [ ] → ETArr N i l | j : : j s → l e t ETJson j ’ = t j s o n o f u j s o n j in l e t ETArr js ’ = t a r r o f u a r r j s in ETArr ( j ’ : : js ’ ) 21/ 48

  29. Building GADT values with existentials type e t j s o n = ETJson : ’ a t j s o n → e t j s o n type e t a r r = ETArr : ’ a t a r r → e t a r r l e t rec t j s o n o f u j s o n : ujson → e t j s o n = f u n c t i o n UStr s → ETJson ( Str s ) (* Str s : string tjson *) | UNum u → ETJson (Num u) | UBool b → ETJson ( Bool b) | UNull → ETJson Null | UArr a r r → l e t ETArr arr ’ = t a r r o f u a r r a r r in ETJson ( Arr arr ’ ) and t a r r o f u a r r : ujson l i s t → e t a r r = f u n c t i o n [ ] → ETArr N i l | j : : j s → l e t ETJson j ’ = t j s o n o f u j s o n j in l e t ETArr js ’ = t a r r o f u a r r j s in ETArr ( j ’ : : js ’ ) 21/ 48

Recommend


More recommend