Generic grouping and sorting RALF HINZE Institut f¨ ur Informatik III, Universit¨ at Bonn R¨ omerstraße 164, 53117 Bonn, Germany Email: ralf@informatik.uni-bonn.de Homepage: http://www.informatik.uni-bonn.de/~ralf October, 2005 (Pick up the slides at .../~ralf/talks.html#T45 .) 1 ◮ ✷ ◭ ◭ ◭ ◮ ◮
Equivalence relation over a type Capture equivalence relations using a generalized algebraic data type (GADT): data Equiv :: ⋆ → ⋆ where Char :: Equiv Char IgnoreCase :: Equiv Char :: Equiv () Unit :: Equiv τ 1 → Equiv τ 2 → Equiv ( τ 1 + τ 2 ) Sum :: Equiv τ 1 → Equiv τ 2 → Equiv ( τ 1 × τ 2 ) Pair :: Equiv τ → Equiv [ τ ] List :: Equiv τ → Equiv [ τ ] Bag ☞ Set omitted. 2 ◮ ✷ ◭ ◭ ◭ ◮ ◮
Overview related :: ( Equiv τ ) → τ → τ → Bool :: ( Equiv τ ) → [ τ ] → [ τ ] sort group :: ( Equiv τ ) → [( τ, ν )] → [( τ, [ ν ])] 3 ◮ ✷ ◭ ◭ ◭ ◮ ◮
Are two elements related? related :: ( Equiv τ ) → τ → → Bool τ ( Char ) = x related x y y ( IgnoreCase ) x = toUpper x related y toUpper y related ( Unit ) x y = True related ( Sum r 1 r 2 ) ( Inl x 1 ) ( Inl y 1 ) = related ( r 1 ) x 1 y 1 ( Sum r 1 r 2 ) ( Inl x 1 ) ( Inr y 2 ) = False related ( Sum r 1 r 2 ) ( Inr x 2 ) ( Inl y 1 ) = False related ( Sum r 1 r 2 ) ( Inr x 2 ) ( Inr y 2 ) = related ( r 2 ) x 2 y 2 related ( Pair r 1 r 2 ) ( x 1 , x 2 ) ( y 1 , y 2 ) related = related ( r 1 ) x 1 y 1 ∧ related ( r 2 ) x 2 y 2 ( Bag r ) related xs ys = related ( List r ) ( sort ( r ) xs ) ( sort ( r ) ys ) ☞ The List case can be done generically (not shown). The IgnoreCase and the Bag case are done via normalization. 4 ◮ ✷ ◭ ◭ ◭ ◮ ◮
Generic sorting sort :: ( Equiv τ ) → [ τ ] → [ τ ] sort ( Char ) xs = sortChar xs ( IgnoreCase ) xs = sort ( Char ) [ toUpper x | x ← xs ] sort ( Unit ) xs = xs sort ( Sum r 1 r 2 ) xs = [ Inl y 1 | y 1 ← sort ( r 1 ) [ x 1 | Inl x 1 ← xs ]] sort + + [ Inr y 2 | y 2 ← sort ( r 2 ) [ x 2 | Inr x 2 ← xs ]] ( Pair r 1 r 2 ) xs = [( x 1 , y 2 ) | ( x 1 , ys 2 ) ← group ( r 1 ) xs sort , y 2 ← sort ( r 2 ) ys 2 ] ( Bag r ) xs = sort ( List r ) [ sort ( r ) x | x ← xs ] sort 5 ◮ ✷ ◭ ◭ ◭ ◮ ◮
Generic grouping group :: ( Equiv τ ) → [( τ, ν )] → [( τ, [ ν ])] group ( Char ) xs = groupChar xs group ( IgnoreCase ) xs = group ( Char ) [( toUpper x , v ) | ( x , v ) ← xs ] ( Unit ) xs = make (() , [ v | (() , v ) ← xs ]) group ( Sum r 1 r 2 ) group xs = [( Inl y 1 , vs ) | ( y 1 , vs ) ← group ( r 1 ) [( x 1 , v ) | ( Inl x 1 , v ) ← xs ]] + + [( Inr y 2 , vs ) | ( y 2 , vs ) ← group ( r 2 ) [( x 2 , v ) | ( Inr x 2 , v ) ← xs ]] ( Pair r 1 r 2 ) group xs = [ (( a 1 , a 2 ) , vs ) | ( a 1 , ys ) ← group ( r 1 ) [( a 1 , ( a 2 , v )) | (( a 1 , a 2 ) , v ) ← xs ] , ( a 2 , vs ) ← group ( r 2 ) ys ] ( Bag r ) xs = group ( List r ) [( sort ( r ) x , v ) | ( x , v ) ← xs ] group 6 ◮ ✷ ◭ ◭ ◭ ◮ ◮
Generic grouping — continued make :: ( τ, [ ν ]) → [( τ, [ ν ])] make ( a , [ ]) = [ ] make ( a , xs ) = [( a , xs )] 7 ◮ ✷ ◭ ◭ ◭ ◮ ◮
Dealing with arbitrary data types The top-level structure of a list: fromList :: [ τ ] → () + τ × [ τ ] [ ] = Inl () fromList ( x : xs ) = Inr ( x , xs ) fromList toList :: () + τ × [ τ ] → [ τ ] ( Inl ()) = [ ] toList ( Inr ( x , xs )) = x : xs toList An equivalence relation for the top-level structure: list :: Equiv τ → Equiv (() + τ × [ τ ]) = Sum Unit ( Pair r ( List r )) list r The missing piece for related : related ( List r ) xs ys = related ( list r ) ( fromList xs ) ( fromList ys ) 8 ◮ ✷ ◭ ◭ ◭ ◮ ◮
Recommend
More recommend