Scrap your boilerplate with class - PowerPoint PPT Presentation

1 / 33
About This Presentation
Title:

Scrap your boilerplate with class

Description:

The seductive dream: customisable generic programming. Define a function generically ' ... Data dictionary contains a cxt dictionary. class (cxt a) = Data cxt ... – PowerPoint PPT presentation

Number of Views:107
Avg rating:3.0/5.0
Slides: 34
Provided by: peyton7
Category:

less

Transcript and Presenter's Notes

Title: Scrap your boilerplate with class


1
Scrap your boilerplate with class
  • Ralf Lämmel, Simon Peyton Jones
  • Microsoft Research

2
The seductive dream customisable generic
programming
  • Define a function genericallygsize t 1
    gsize of ts children
  • Override the generic defn at specific
    typesgsize of a string is the length of the
    string
  • Use the generic function at any typegsize

3
1. Generic definition TLDI03
gsize Data a a - Int gsize t 1 sum
(gmapQ gsize t) class Data a where gmapQ
(forall b. Data b b - r) - a - r--
(gmapQ f t) applies f to each of ts-- children,
returning list of results
  • NB Cool higher rank type for gmapQ

4
Need Data instance for each type (once and for
all)
class Data a where gmapQ (forall b. Data b
b - r) - a - r-- (gmapQ f t) applies
f to each of ts-- children, returning list of
results instance Data Int wheregmapQ f i
instance Data a Data a wheregmapQ f
gmapQ f (xxs) f x, f xs
  • Higher rank type

5
The seductive dream customisable generic
programming
  • Define a function genericallygsize t 1
    gsize of ts children
  • Override the generic defn at specific
    typesgsize of a string is the length of the
    string
  • Use the generic function at any typegsize

Done!
6
Override gsize at specific type
  • Plan A dynamic type test TLDI03

gsizeString Char - Int gsizeString s
length s gsize Data a a - Int gsize (\t
- 1 sum (gmapQ gsize t)) extQ
gsizeString
7
The seductive dream customisable generic
programming
  • Define a function genericallygsize t 1
    gsize of ts children
  • Override the generic defn at specific
    typesgsize of a string is the length of the
    string
  • Use the generic function at any typegsize

Done!
Done!
8
Not quite...
  • Problems with Plan A
  • Dynamic type test costs
  • No static check for overlap
  • Fiddly for type constructors ICFP04
  • Worst of all tying the knot prevents further
    extension

gsize Data a a - Int gsize t (1 sum
(gmapQ gsize t)) extQ gsizeString
9
Tantalising Plan B type classes
class Size a where gsize a - Int instance
Size a Size a where gsize xs length xs
  • Can add new types, with type-specific instances
    for gsize, later
  • No dynamic type checks
  • Plays nicely with type constructors

10
...BUT
  • Boilerplate instance required for each new type,
    even if only the generic behaviour is wanted

data MyType a MT Int a instance Size a Size
(MyType a) where gsize (MT i x) 1 gsize i
gsize x data YourType a YT a a instance Size
a Size (YourType a) where gsize (YT i j) 1
gsize i gsize j
11
The seductive dream customisable generic
programming
  • Define a function genericallygsize t 1
    gsize of ts children
  • Override the generic defn at specific
    typesgsize of a string is the length of the
    string
  • Use the generic function at any typegsize

Undone!
Done better!
12
Writing the generic code
  • Why cant we combine the two approaches, like
    this?

Generic case
class Size a where gsize a - Int instance
Data t Size t wheregsize t 1 sum (gmapQ
gsize t) instance Size a Size a where ...
More specific cases over-ride
13
...utter failure
instance Data t Size t wheregsize t 1 sum
(gmapQ gsize t)
gmapQ Data a (forall b. Data b b -
r) - a - r gsize Size b b - Int
(gmapQ gsize t) will give a Data dictionary to
gsize...
...but alas gsize needs a Size dictionary
14
Idea (bad)
Make a Data dictionary contain a Size dictionary
class Size a Data a wheregmapQ (forall b.
Data b b - r) - a - r
Now the instance works... but the idea is a
non-starter For every new generic function,
wed have to add a new super-class to
Data, ...which is defined in a library
15
Much Better Idea
Main idea of the talk
Parameterise over the superclass Hughes
1999Data dictionary contains a cxt dictionary
class (cxt a) Data cxt a wheregmapQ
(forall b. Data cxt b b - r) - a -
r
  • cxt has kind -pred
  • just as
  • a has kind

16
Much Better Idea nearly works
instance Data Size t Size t wheregsize t 1
sum (gmapQ gsize t)
gmapQ Data cxt a (forall b. Data cxt b
b - r) - a - r gsize Size b b - Int
(gmapQ gsize t) will give a (Data Size t)
dictionary to gsize...
...and gsize can get the Size dictionary from
inside it
17
The seductive dream customisable generic
programming
  • Define a function genericallygsize t 1
    gsize of ts children
  • Override the generic defn at specific
    typesgsize of a string is the length of the
    string
  • Use the generic function at any typegsize

Done again!
Done better!
18
Story so far
  • We can write a generic program once

class Size a wheregsize a - Int
instance Data Size t Size t where ...
  • Later, define a new type

data Wibble ... deriving( Data )
  • Optionally, add type-specific behaviour

instance Size Wibble where ...
  • In short, happiness regular Haskell type-class
    overloading plus generic definition

19
Things I swept under the carpet
  • Type inference fails
  • Haskell doesnt have abstraction over type
    classes
  • Recursive dictionaries are needed

20
Type inference fails
(Data Size t) dictionary available...
instance Data Size t Size t wheregsize t 1
sum (gmapQ gsize t)
(Data cxt t) dictionary required...
...but no way to know that cxt Size
gmapQ Data cxt a (forall b. Data cxt b
b - r) - a - r
21
Type inference fails
instance Data Size t Size t wheregsize t 1
sum (gmapQ gsize t)
We really want to specify that cxt should be
instantiated by Size, at this call site
gmapQ Data cxt a (forall b. Data cxt b
b - r) - a - r
22
Type proxy value argument
instance Data Size t Size t wheregsize t 1
sum (gmapQ gsProxy gsize t)
data Proxy (cxt -pred) gsProxy Proxy
Size gsProxy error urk
Type-proxy argument
Type-proxy argument
gmapQ Data cxt a Proxy cxt - (forall b.
Data cxt b b - r) - a - r
23
Things I swept under the carpet
Done! (albeit still tiresome)
  • Type inference fails
  • Haskell doesnt have abstraction over type
    classes
  • Recursive dictionaries are needed

24
Recursive dictionaries
instance (Data cxt a, cxt a) Data cxt a
wheregmapQ f gmapQ f (xxs) f x, f
xs
(I1)
instance Data Size t Size t wheregsize t 1
sum (gmapQ gsize t)
(I2)
  • Need (Size Int)
  • Use (I2) to get it from (Data Size Int)
  • Use (I1) to get that from (Data Size Int, Size
    Int)

25
Recursive dictionaries
i1 (Data cxt a, cxt a) - Data cxt a i2
Data Size t - Size t i3 Data cxt Int
rec d1Size Int i2 d2 d2Data Size
Int i1 (d3,d1) d3Data Size Int i3
  • Need (Size Int)
  • Use (I2) to get it from (Data Size Int)
  • Use (I1) to get that from (Data Size Int, Size
    Int)

26
Recursive dictionaries
  • Recursive dictionaries arise naturally from
    solving constraints co-inductively
  • Coinduction to solve C, assume C, and then prove
    Cs sub-goals
  • Sketch of details in paper formal details in
    Sulzmann 2005

27
Things I swept under the carpet
Done!
  • Type inference fails
  • Haskell doesnt have abstraction over type
    classes
  • Recursive dictionaries are needed

Done!
28
Encoding type-class abstraction
  • Wanted (cxt-pred)

class (cxt a) Data cxt a wheregmapQ
(forall b. Data cxt b b - r) - a -
r
Encoding (cxt-)
class Sat (cxt a) Data cxt a wheregmapQ
(forall b. Data cxt b b - r) - a -
r class Sat a wheredict a
29
Encoding type-class abstraction
  • Wanted (Size-pred)

instance Data Size t Size t wheregsize t 1
sum (gmapQ gsize t)
Encoding (SizeD-)
instance Data SizeD t Size t wheregsize t 1
sum (gmapQ (gsizeD dict) t) data SizeD a SD
(a - Int) gsizeD (SD gs) gs instance Size a
Sat (SizeD a) wheredict SD gsize
30
Encoding type-class abstraction
  • Details straightforward. Its a little fiddly,
    but not hard
  • A very cool trick
  • Does Haskell need native type-class abstraction?

31
Summary
SYB home pagehttp//www.cs.vu.nl/boilerplate/
  • A smooth way to combine generic functions with
    the open extensibility of type-classes
  • No dynamic type tests, although they are still
    available if you want them, via (Data Typeable
    a)
  • Longer case study in paper
  • Language extensions
  • coinductive constraint solving (necessary)
  • abstraction over type classes (convenient)

32
Recursive dictionaries
Known instances
Constraint to be solved
  • Solve( S, C )
  • Solve( S, D1 ) if S contains... instance
    (D1..Dn) CSolve( S, Dn )

33
Recursive dictionaries
Known instances
Constraint to be solved
  • Solve( S, C )
  • Solve( S ? C, D1 ) if S contains... instance
    (D1..Dn) CSolve( S ? C, Dn )

Coinduction to solve C, assume C, and then
prove Cs sub-goals (cf Sulzmann05)
Write a Comment
User Comments (0)
About PowerShow.com