datatypes and patterns
play

Datatypes and Patterns Datatypes Amtoft from Hatcliff Type Names - PowerPoint PPT Presentation

Datatypes and Patterns Datatypes Amtoft from Hatcliff Type Names Datatypes Patterns Local Definitions ML datatypes and patterns can make programs much more concise and elegant 1. type abbreviations 2. ML datatypes 3. patterns and local


  1. Datatypes and Patterns Datatypes Amtoft from Hatcliff Type Names Datatypes Patterns Local Definitions ML datatypes and patterns can make programs much more concise and elegant 1. type abbreviations 2. ML datatypes 3. patterns and local variables

  2. Simple Type Abbreviations Datatypes Amtoft from Hatcliff Type Names Syntax: Datatypes type � identifier � = � type expression � Patterns Local Definitions Semantics: type makes an abbreviation, not a new type. − type s i g n a l = i n t l i s t ; s i g n a l = i n t l i s t type − val v = [ 1 , 2 , 3 ] : s i g n a l ; val v = [ 1 , 2 , 3 ] : s i g n a l − val w = [ 1 , 2 , 3 ] ; val w = [ 1 , 2 , 3 ] : i n t l i s t − v = w; val i t = true : bool − hd v ; val i t = 1 : i n t

  3. Parametric Type Abbreviations Datatypes Amtoft from Hatcliff Type Names Datatypes Syntax: Patterns type ( � type parameters � ) � identifier � = Local Definitions � type expression � Semantics: a family of abbreviations − type ( ’ k , ’ v ) t a b l e = ( ’ k ∗ ’ v ) l i s t ; type ( ’ a , ’ b) t a b l e = ( ’ a ∗ ’b) l i s t − [ ( ”bob” ,1) ,( ” jane ” , 2 ) ] : ( s t r i n g , i n t ) t a b l e ; i t = [ ( ”bob” ,1) ,( ” jane ” , 2 ) ] val : ( s t r i n g , i n t ) t a b l e

  4. ML Datatype Facility Datatypes Amtoft from Hatcliff Type Names Datatypes Patterns Local Definitions ◮ the ML datatype facility allows one to create tree structured data ◮ very flexible abstract mechanism for representing structured data

  5. Simple Sum Types Datatypes Amtoft from Hatcliff Type Names datatype s u i t = Datatypes Clubs | Diamonds Patterns | Hearts | Spades Local Definitions − Clubs ; i t = Clubs : s u i t val datatype card = Club i n t | Diamond of i n t of | Heart of i n t | Spade of i n t | WildCard − Heart 7; i t = Heart 7 : card val

  6. Parametrized Sum Types Datatypes Amtoft from Hatcliff Type Names Datatypes Patterns Local Definitions datatype ( ’ a , ’b) p a i r o r s i n g l e = Pair ’ a ∗ ’b of | S i n g l e of ’ a − [ Pair ( ”ab” ,7) , S i n g l e ”cd” ] ; val i t = [ Pair ( ”ab” ,7) , S i n g l e ”cd” ] : ( s t r i n g , i n t ) p a i r o r s i n g l e l i s t

  7. Recursive Types Datatypes Amtoft from Hatcliff Type Names datatype i n t t r e e = Datatypes Leaf of i n t Patterns | Node of i n t ∗ i n t t r e e ∗ i n t t r e e Local Definitions − Node (5 , Node (5 , Leaf 4 , Leaf 7) , Leaf 3 ) ; val i t = Node (5 , Node (5 , Leaf #,Leaf #), Leaf 3) : i n t t r e e We may generalize to other types than int ’ a t r e e = datatype Lf ’ a of | Nd of ’ a ∗ ’ a t r e e ∗ ’ a t r e e − Lf ; val i t = fn : ’ a − > ’ a t r e e

  8. Parametrized Recursive Types Datatypes Amtoft from Hatcliff ’ a t r e e = datatype Type Names Lf ’ a of Datatypes | Nd of ’ a ∗ ’ a t r e e ∗ ’ a t r e e Patterns Local Definitions − Lf ; val i t = fn : ’ a − > ’ a t r e e − Nd ( 3 . 0 , Lf ( 3 . 5 ) , Lf ( 4 . 2 ) ) ; val i t = Nd ( 3 . 0 , Lf 3.5 , Lf 4.2) : r e a l t r e e − Nd (3 , Lf (5) , Lf ( 4 ) ) ; val i t = Nd (3 , Lf 5 , Lf 4) : i n t t r e e − Nd (3 , Lf ( 5 . 0 ) , Lf ( 4 . 6 ) ) ; . . Error : operator and operand don ’ t agree . . operator domain : i n t ∗ i n t t r e e ∗ i n t t r e e operand : i n t ∗ r e a l t r e e ∗ r e a l t r e e

  9. General Form of Data Types Datatypes Amtoft from Hatcliff ( � type parameters � ) � identifier � datatype = Type Names � first constructor expression � | Datatypes � second constructor expression � Patterns | Local Definitions ... | � last constructor expression � We have already seen the predefined option types: datatype ’ a option = NONE | SOME of ’ a List is the quintessential datatype; conceptually datatype ’ a l i s t = n i l | : : of ’ a ∗ ’ a l i s t

  10. Case Patterns Datatypes Amtoft from Hatcliff many tests x = fun Type Names x = n i l i f Datatypes then 0 Patterns t l ( x ) = n i l else i f Local Definitions then 1 else i f hd ( x ) = 3 andalso t l ( x ) = [ 2 ] then 6 else 12; can be written more concisely using case patterns: many tests x = fun case x of n i l = > 0 | ( : : n i l ) = > 1 | (3 : : (2 : : n i l )) = > 6 | = > 12; ◮ the wildcard (“underscore”) matches anything. ◮ Patterns can be nested

  11. Patterns Save Computation Datatypes Amtoft from Hatcliff fun a c c e s s e s x = Type Names i f x = n i l Datatypes then 0 Patterns hd ( x ) < 20 else i f Local Definitions then hd ( x ) 30 else involves taking hd of x twice. This is avoided by: a c c e s s e s n i l = 0 fun | a c c e s s e s (n : : ns ) = n < 20 then n else 30 i f ◮ Variables used in patterns are bound to values (p.73) ◮ fun has an implicit case statement as has fn : a c c e s s e s = val n i l = > 0 fn | (n : : ns ) = > i f n < 20 then n else 30

  12. Having it Both Ways Datatypes Amtoft from Hatcliff Merging two sorted lists: Type Names − fun merge ( n i l ,M) = M | merge (L , n i l ) = L Datatypes | merge (L ,M) = i f hd (L) < hd (M) Patterns then hd (L ) : : merge ( t l (L ) ,M) Local Definitions else hd (M) : : merge (L , t l (M) ) ; Introduce case patterns: − fun merge ( n i l ,M) = M | merge (L , n i l ) = L | merge ( x : : xs , y : : ys ) = i f x < y then x : : merge ( xs , y : : ys ) y : : merge ( x : : xs , ys ) ; else but now x :: xs has to be recomputed. Use “ as ”: − fun merge ( n i l ,M) = M | merge (L , n i l ) = L | merge (L as x : : xs , M as y : : ys ) = i f x < y then x : : merge ( xs ,M) y : : merge (L , ys ) ; else as names the entire data plus destructs it using a pattern.

  13. Patterns Should be Exhaustive Datatypes Amtoft from Hatcliff − fun non exhaustive n i l = 0; Type Names . . . Warning : match nonexhaustive Datatypes n i l = > . . . Patterns Local Definitions val non exhaustive = fn : ’ a l i s t − > i n t − non exhaustive n i l ; i t = 0 : i n t val − non exhaustive [ 1 , 2 ] ; uncaught exception Match . . . A non-exhaustive pattern ◮ causes a compile-time warning ◮ can cause a run-time exception for data corresponding to missing cases ◮ still might be appropriate if we know we will never encounter certain data

  14. Pattern Matching versus Unification Datatypes Amtoft from Hatcliff Type Names − fun t e s t p a i r (p : i n t ∗ i n t ) = Datatypes i f #1(p) = #2(p) then ” yes ” else ”no” ; Patterns Local Definitions val t e s t p a i r = fn : i n t ∗ i n t − > s t r i n g We would like to rewrite to − fun t e s t p a i r (n , n) = ” yes ” | t e s t p a i r = ”no” ; . . Error : d u p l i c a t e v a r i a b l e pattern ( s ) : n in ◮ a variable cannot be repeated in the same pattern ◮ this would be equivalent to unification ◮ which is a more powerful technique (used, e.g., in Prolog)

  15. Local Variables Datatypes Amtoft from Hatcliff Type Names Datatypes double x = x + x ; fun Patterns fun dupdouble x y = Local Definitions [ ( double ( x ) , double ( y )) , ( double ( x ) , double ( y ) ) ] ; The let construct declares local variables fun dupdouble x y = l e t val a = double ( x ) ; val b = double ( y ) in [ ( a , b ) ,( a , b ) ] end ; and thus avoids duplicating computation

  16. Patterns for Return Values Datatypes Amtoft from Hatcliff Type Names Datatypes When a local variable is bound to the result of a function Patterns Local Definitions fun s p l i t e m x = z = dupdouble x x l e t val in (#1(hd ( t l ( z ))) ,#2( hd ( t l ( z ) ) ) ) end ; we may decompose that result using patterns: s p l i t e m x = fun [ q , ( s , t ) ] = dupdouble x x l e t val ( s , t ) in end ;

Recommend


More recommend