230 likes | 373 Views
Advanced Functional Programming. Tim Sheard Oregon Graduate Institute of Science & Technology. Lecture 9: Non Regular types. Acknowledgements. The ideas in this lecture come from the paper: From Fast Exponentiation to Square Matrices: An Adventure in Types. By Chris Okasaki
E N D
Advanced Functional Programming • Tim Sheard • Oregon Graduate Institute of Science & Technology • Lecture 9: • Non Regular types
Acknowledgements • The ideas in this lecture come from the paper: • From Fast Exponentiation to Square Matrices: • An Adventure in Types. • By Chris Okasaki • Proceedings of the 1999 ACM SIGPLAN International Conference on Functional Programming. • Paris France, Sept. 27-29, 1999
2 5 0 1 4 7 1 Quad trees • type Quad a = (a,a,a,a) • data Quadtree a • = Z a • | S (Quad (Quadtree a)) • ex1 = S(Z 2,Z 5, Z 0, • S(Z 1,Z 4,Z 7,Z 1))
functions by pattern matching • mapQ :: (a -> b) -> Quadtree a -> Quadtree b • mapQ f (Z x) = Z(f x) • mapQ f (S(w,x,y,z)) = • S(mapQ f w,mapQ f x,mapQ f y,mapQ f z)
Now consider • data QT2 a = Z2 a • | S2 (QT2(Quad a)) • -- S2 :: QT2 (Quad a) -> QT2 a • -- S2 :: QT2 (a,a,a,a) -> QT2 a
Shapes • -- Note how things of type Quadtree can have any shape • ex1 = S(Z 2,Z 5, Z 0,S(Z 1,Z 4,Z 7,Z 1)) • -- Including square things • ex2 = S(S(Z 1, Z 2, Z 3, Z 4) • ,S(Z 5, Z 6, Z 7, Z 8) • ,S(Z 9, Z 10, Z 11, Z 12) • ,S(Z 13, Z 14, Z 15, Z 16)) • -- But things of type QT2 can only be square • ex3 = S2(S2(Z2(( 1, 2, 3, 4), • ( 5, 6, 7, 8), • ( 9,10,11,12), • (13,14,15,16))))
Problems? • data QT2 a = Z2 a • | S2 (QT2(Quad a)) Parameterized by a Parameterized by (Quad a)
map for QT2 • data QT2 a = Z2 a • | S2 (QT2(Quad a)) • mapQ2 :: (a -> b) -> QT2 a -> QT2 b • mapQ2 f (Z2 x) = Z2(f x) • mapQ2 f (S2 z) = • S2(mapQ2 (mapQuad f) z) • where mapQuad f (a,b,c,d) = • (f a, f b, f c, f d) • what type does the italicizedmapQ2 have?
Other sizes • How could you make a 3 by 3 square matrix? • type Tri a = (a,a,a) • -- TT = Tri Trees • data TT a = Z3 a • | S3 (TT(Tri a)) • ex4 = S3 (S3 (Z3 ((1,2,3), • (4,5,6), • (7,8,9))))
Non powers of 2? • power b n = fast 1 b n • fast acc b n • | n==0 = acc • | even n = fast acc (b*b) (half n) • | odd n = fast (acc*b) (b*b) (half n) • half :: Int -> Int • half x = div x 2 • power 2 7 = fast 1 2 7 = fast (1*2) 4 3 = • fast (1*2*4) 16 1 = fast (1*2*4*16) 32 0 = • 1*2*4*16 = 128
Lift to the type level • type Vector a = Vector_ () a • data Vector_ v w • = Zero v • | Even (Vector_ v (w,w)) • | Odd (Vector_ (v,w) (w,w))
An Example data Vector_ v w = Zero v | Even (Vector_ v (w,w)) | Odd (Vector_ (v,w) (w,w)) Vector_ () a 1 Odd Vector_ ((),a) (a,a) Even 0 Vector_ ((),a) ((a,a),(a,a)) 1 Odd Vector_ (((),a),((a,a),(a,a))) (((a,a),(a,a)),((a,a),(a,a))) Zero (((),a),((a,a),(a,a))) Vector with 5 elements 5 = 101 in base 2 (((),1),((2,3),(4,5)))
Making an element Why do we need the the function prototype? • create x n = create_ () x n • create_ :: v -> w -> Int -> Vector_ v w • create_ v w n • | n==0 = Zero v • | even n = Even (create_ v (w,w) (half n)) • | odd n = Odd (create_ (v,w) (w,w) (half n)) • create 1 5 = create_ () 1 5 = • Odd(create_ ((),1) (1,1) 2) = • Odd(Even(create_ ((),1) ((1,1),(1,1)) 1)) = • Odd(Even(Odd(create_ (((),1),((1,1),(1,1))) • (((1,1),(1,1)),((1,1),(1,1))) 0 = • Odd(Even(Odd(Zero (((),1),((1,1),(1,1))))))
Rectangular arrays • To create rectangular arrays, we repeat the definition and place Vector at the leaf (Zero) node. • type Rect a = Rect_ () a • data Rect_ v w • = ZeroR (Vector v) • | EvenR (Rect_ v (w,w)) • | OddR (Rect_ (v,w) (w,w))
Square Arrays • Consider • data Rect_ v w • = ZeroR (Vector v) • | EvenR (Rect_ v (w,w)) • | OddR (Rect_ (v,w) (w,w)) • When we get to ZeroR "v" is a type. Suppose "v" was a type constructor, then we could apply "v" twice, as in v(v a) to get a square matrix.
List the idea to type construtors • the empty vector • newtype Empty a = E () • the vector of size 1 • newtype Id a = I a • vectors of size v + w • newtype Pair v w a = P(v a,w a)
Square Vectors • type Square a = • Square_ Empty Id a • data Square_ v w a • = ZeroS (v(v a)) • | EvenS (Square_ v (Pair w w) a) • | OddS (Square_ (Pair v w) • (Pair w w) a) What is the kind of square_ ?
Example 2 by 2 array • row1 = P (E (),P(I 3,I 4)) • row2 = P (E (),P(I 5,I 6)) • table = P(E (),P(I row1, I row2)) • Note the repeating pattern since we have: • v(v Int) • pat x y = P(E(),P(I x,I y)) • z = EvenS(OddS (ZeroS table))
2 by 2 array • 2 = 10 in base 2 • 0 1 • EvenS (OddS (ZeroS • ((),(((),(3,4)),((),(5,6))))))
4 by 4 array • h w x y z = P(E(), P(P(I w,I x),P(I y,I z))) • r1 = h 1 2 3 4 • r2 = h 5 6 7 8 • r3 = h 9 10 11 12 • r4 = h 13 14 15 16 • tab = h r1 r2 r3 r4 • 4= 100 in base 2 • 0 0 1 • dd = EvenS(EvenS(OddS(ZeroS tab)))
dd= • EvenS (EvenS (OddS (Square(ZeroS • ((),((((),((1, 2 ),(3, 4))), • ((),((5, 6 ),(7,8)))), • (((),((9, 10),(11,12))), • ((),((13,14),(15,16)))))))))
Indexing • First for primitive vectors • subE i (E ()) = • error "no index in empty vector" • subI 0 (I x) = x • subI n (I x) = • error "only 0 can index vector of size 1" • subP subv subw vsize i (P (v,w)) • | i < vsize = subv i v • | i >= vsize = subw (i-vsize) w
sub (i,j) m = sub_ subE subI 0 1 (i,j) m • sub_ :: (forall b. Int -> v b -> b) -> • (forall b. Int -> w b -> b) -> • Int -> Int -> (Int,Int) -> • Square_ v w a -> a • sub_ subv subw vsize wsize (i,j) x = • case x of • ZeroS vv -> subv i (subv j vv) • EvenS m -> sub_ subv (subP subw subw wsize) • vsize (wsize+wsize) (i,j) m • OddS m -> sub_ (subP subv subw vsize) • (subP subw subw wsize) • (vsize+wsize) (wsize+wsize) (i,j) m