GADTs GADTs in Haskell. ADT vs GADT Algebraic Datatype Data List a = Nil | Cons a (List a) Data Tree a b = Tip a | Node (Tree a b) b | Fork (Tree a b)

Slides:



Advertisements
Similar presentations
Chapter 13. Red-Black Trees
Advertisements

ML Datatypes.1 Standard ML Data types. ML Datatypes.2 Concrete Datatypes  The datatype declaration creates new types  These are concrete data types,
0 PROGRAMMING IN HASKELL Chapter 10 - Declaring Types and Classes.
ML: a quasi-functional language with strong typing Conventional syntax: - val x = 5; (*user input *) val x = 5: int (*system response*) - fun len lis =
Analysis of Algorithms CS 477/677 Instructor: Monica Nicolescu Lecture 11.
Lecture 12: Balanced Binary Search Trees Shang-Hua Teng.
A Type System for MetaML MetaML types as an Omega program Lecture 12.
Tirgul 10 Rehearsal about Universal Hashing Solving two problems from theoretical exercises: –T2 q. 1 –T3 q. 2.
CS 206 Introduction to Computer Science II 11 / 19 / 2008 Instructor: Michael Eckmann.
1 /26 Red-black tree properties Every node in a red-black tree is either black or red Every null leaf is black No path from a leaf to a root can have two.
1 /26 Red-black tree properties Every node in a red-black tree is either black or red Every null leaf is black No path from a leaf to a root can have two.
1 Binary Search Trees Implementing Balancing Operations –AVL Trees –Red/Black Trees Reading:
AVL Trees ITCS6114 Algorithms and Data Structures.
Balanced Search Trees CS 3110 Fall Some Search Structures Sorted Arrays –Advantages Search in O(log n) time (binary search) –Disadvantages Need.
C o n f i d e n t i a l HOME NEXT Subject Name: Data Structure Using C Unit Title: Trees.
Red-Black Trees Lecture 10 Nawazish Naveed. Red-Black Trees (Intro) BSTs perform dynamic set operations such as SEARCH, INSERT, DELETE etc in O(h) time.
Staging in Haskell What is Staging What does it Mean Using Template Haskell.
PrasadCS7761 Haskell Data Types/ADT/Modules Type/Class Hierarchy Lazy Functional Language.
AVL Trees Neil Ghani University of Strathclyde. General Trees Recall a tree is * A leaf storing an integer * A node storing a left subtree, an integer.
CMSC 341 Introduction to Trees. 8/3/2007 UMBC CMSC 341 TreeIntro 2 Tree ADT Tree definition  A tree is a set of nodes which may be empty  If not empty,
Red-Black Trees CS302 Data Structures Dr. George Bebis.
Analysis of Red-Black Tree Because of the rules of the Red-Black tree, its height is at most 2log(N + 1). Meaning that it is a balanced tree Time Analysis:
Red-Black Trees Red-black trees: –Binary search trees augmented with node color –Operations designed to guarantee that the height h = O(lg n)
CS-2851 Dr. Mark L. Hornick 1 Okasaki’s Insertion Method for Red/Black balancing A step-by-step procedure for maintaining balance through application of.
CSIT 402 Data Structures II
1 Red-Black Trees By Mary Hudachek-Buswell Red Black Tree Properties Rotate Red Black Trees Insertion Red Black Trees.
Lecture 10 Algorithm Analysis Arne Kutzner Hanyang University / Seoul Korea.
2IL50 Data Structures Fall 2015 Lecture 7: Binary Search Trees.
Lee CSCE 314 TAMU 1 CSCE 314 Programming Languages Haskell: Types and Classes Dr. Hyunyoung Lee.
1 Data Structures and Algorithms Searching Red-Black and Other Dynamically BalancedTrees.
Data Structures and Algorithms TREE-TRAVERSAL. Searching - Re-visited Binary tree O(log n) if it stays balanced Simple binary tree good for static collections.
CMSC 341 B- Trees D. Frey with apologies to Tom Anastasio.
Outline Binary Trees Binary Search Tree Treaps. Binary Trees The empty set (null) is a binary tree A single node is a binary tree A node has a left child.
1 CS 457/557: Functional Languages Lists and Algebraic Datatypes Mark P Jones Portland State University.
Week 10 - Friday.  What did we talk about last time?  Graph representations  Adjacency matrix  Adjacency lists  Depth first search.
CMSC 341 Introduction to Trees. 2/21/20062 Tree ADT Tree definition –A tree is a set of nodes which may be empty –If not empty, then there is a distinguished.
Week 15 – Wednesday.  What did we talk about last time?  Review up to Exam 1.
Red-Black Tree Insertion Start with binary search insertion, coloring the new node red NIL l Insert 18 NIL l NIL l 1315 NIL l
1 Binary Search Trees  Average case and worst case Big O for –insertion –deletion –access  Balance is important. Unbalanced trees give worse than log.
More Data Types CSCE 314 Spring CSCE 314 – Programming Studio Defining New Data Types Three ways to define types: 1.type – Define a synonym for.
Environments, Stores, and Interpreters. Overview As we study languages we will build small languages that illustrate language features We will use two.
Advanced Tree Structures Binary Trees, AVL Tree, Red-Black Tree, B-Trees, Heaps SoftUni Team Technical Trainers Software University
1 CMSC 341 Introduction to Trees Textbook sections:
Red-Black Trees an alternative to AVL trees. Balanced Binary Search Trees A Binary Search Tree (BST) of N nodes is balanced if height is in O(log N) A.
Data Structures and Algorithms (AT70.02) Comp. Sc. and Inf. Mgmt. Asian Institute of Technology Instructor: Prof. Sumanta Guha Slide Sources: CLRS “Intro.
CSC317 1 x y γ β α x y γ β x β What did we leave untouched? α y x β.
Lecture 23 Red Black Tree Chapter 10 of textbook
Types CSCE 314 Spring 2016.
Chapter 48 Red Black Trees
ML: a quasi-functional language with strong typing
A lightening tour in 45 minutes
Red Black Trees
AVL DEFINITION An AVL tree is a binary search tree in which the balance factor of every node, which is defined as the difference between the heights of.
CSCI Trees and Red/Black Trees
TREES General trees Binary trees Binary search trees AVL trees
PROGRAMMING IN HASKELL
Lecture 9 Algorithm Analysis
Advanced Functional Programming
Advanced Functional Programming
Lecture 9 Algorithm Analysis
Lecture 9 Algorithm Analysis
Data Structures and Algorithms
Chapter 43 Red Black Trees
2-3-4 Trees Red-Black Trees
Advanced Functional Programming
Types and Classes in Haskell
ITCS6114 Algorithms and Data Structures
Red-black tree properties
Algorithms, CSCI 235, Spring 2019 Lecture 22—Red Black Trees
Tree (new ADT) Terminology: A tree is a collection of elements (nodes)
Presentation transcript:

GADTs GADTs in Haskell

ADT vs GADT Algebraic Datatype Data List a = Nil | Cons a (List a) Data Tree a b = Tip a | Node (Tree a b) b | Fork (Tree a b) (Tree a b) Generalized Algebraic Datatype Data List a where Nil:: List a Cons:: a -> List a -> List a Data Tree a b where Tip a : Tree a b Node: Tree a b -> b -> Tree a b Fork:: Tree a b -> Tree a b -> Tree a b Note that types than can be expressed as an ADT always have the identical range types on all their constructors

GADTs relax the range restriction data Even n where Base:: Even Z NE:: Odd n -> Even (S n) data Rep:: * -> * where Int:: Rep Int Char:: Rep Char Float:: Rep Float Bool :: Rep Bool Pair:: Rep a -> Rep b -> Rep (a,b) List :: Rep a -> Rep [a] The range is always the type being defined, (Even & Rep) but that type’s arguments can vary. We call an argument that varies and index.

Examples Length indexed lists Balanced Trees – Redblack trees – 2-threes trees – AVL trees Representation types Well-typed terms – Terms as typing judgements – Tagless interpreters – Subject reduction – Type inference Witnesses – Odd and Even – Well formed join and cross product in relational algebra Well structured paths in trees Units of measure (inches, centimeters, etc) Provable Equality Proof carrying code

Length indexed lists data Z data S n data LList :: * -> * -> * where LNil:: LList a Z LCons:: a -> LList a n -> LList a (S n) Note we introduce uninhabited types that have the structure of the Natural numbers to serve as indexes to LList Note the range type is always LList But they differ in the indexes.

Promotion As of GHC version 7 GHC allows indexes to be ordinary datatypes. One says the datatype is promoted to the type level. This is very usefull, as it enforces a typing system on the indexes. – For example does (LList Int String) make any sense. The index is supposed to be drawn from Z and S

Length indexed lists again data Nat = Zero | Succ Nat data Vec:: * -> Nat -> * where Nil :: Vec a Zero Cons:: a -> Vec a n -> Vec a (Succ n) An ordinary algebraic datatype The index is always drawn from well typed values of type Nat, so values of type Nat are promoted to Types The type Nat is promoted to a Kind

GADTs as proof objects data EvenX:: Nat -> * where BaseX:: EvenX Zero NEX:: OddX n -> EvenX (Succ n) data OddX:: Nat -> * where NOX:: EvenX n -> OddX (Succ n) What type does NEX (NOX BaseX) have?

The Curry-Howard isomorphism The Curry-Howard isomorphism says that two things have exactly the same structure. – A term has a type – A proof proves a proposition NEX (NOX BaseX) :: EvenX (Succ (Succ Zero)) Note that there is no term with type: EvenX (Succ Zero) Proves a proposition Has a type A term A proof

Proofs and witnesses GADTs make the Curry-Howard isomorphism useful in Haskell. Sometime we say a term “witnesses” a property. I.e the term NEX (NOX BaseX) witnesses that 2 is even. We use GADTs has indexes to show that some things are not possible.

Paths and Trees data Shape = Tp | Nd | Fk Shape Shape data Path :: Shape -> * where Here:: Path Nd Left:: Path x -> Path (Fk x y) Right:: Path y -> Path (Fk x y) data Tree:: Shape -> * -> * where Tip :: Tree Tp a Node:: a -> Tree Nd a Fork :: Tree x a -> Tree y a -> Tree (Fk x y) a Note there are no paths with index Tp

Well formed paths find:: Eq a => a -> Tree sh a -> [Path sh] find n Tip = [] find n (Node m) = if n==m then [Here] else [] find n (Fork x y) = (map Left (find n x)) ++ (map Right (find n y))

Using a path. No possibility of failure extract:: Eq a => Tree sh a -> Path sh -> a extract (Node n) (Here) = n extract (Fork l r) (Left p) = extract l p extract (Fork l r) (Right p) = extract r p -- No other cases are possible, -- Since there are no Paths with index Tp

Balanced Trees Balanced trees are used as binary search mechanisms. They support log(n) time searches for trees that have n elements They rely on the trees being balanced. – Usually saying that all paths from root to leaf have roughly the same length Indexes make perfect tools to represent these invariants.

Red Black Trees A red-black tree is a binary search tree with the following additional invariants: – Each node is colored either red or black – The root is black – The leaves are black – Each Red node has Black children – for all internal nodes, each path from that node to a descendant leaf contains the same number of black nodes. We can encode these invariants by thinking of each internal node as having two attributes: a color and a black-height.

Red Black Tree as a GADT data Color = Red | Black data SubTree :: Color -> Nat -> * where LeafRB :: SubTree Black Zero RNode :: SubTree Black n -> Int -> SubTree Black n -> SubTree Red n BNode :: SubTree cL m -> Int -> SubTree cR m -> SubTree Black (Succ m) data RBTree where Root:: (forall n. (SubTree Black n)) -> RBTree

AVL Trees In an AVL tree, the heights of the two child sub trees of any node differ by at most one; data Balance:: Nat -> Nat -> Nat -> * where Same :: Balance n n n Less :: Balance n (Succ n) (Succ n) More :: Balance (Succ n) n (Succ n) data Avl:: Nat -> * where TipA:: Avl Zero NodeA:: Balance i j k -> Avl i -> Int -> Avl j -> Avl (Succ k) data AVL = forall h. AVL (Avl h) A witness type that witnesses only the legal height differences.

Insertion insert :: Int -> AVL -> AVL insert x (AVL t) = case ins x t of L t -> AVL t; R t -> AVL t ins :: Int -> Avl n -> (Avl n + Avl (Succ n)) ins x TipA = R(NodeA Same TipA x TipA) ins x (NodeA bal lc y rc) | x == y = L(NodeA bal lc y rc) | x < y = case ins x lc of L lc -> L(NodeA bal lc y rc) R lc -> case bal of Same -> R(NodeA More lc y rc) Less -> L(NodeA Same lc y rc) More -> rotr lc y rc -- rebalance | x > y = case ins x rc of L rc -> L(NodeA bal lc y rc) R rc -> case bal of Same -> R(NodeA Less lc y rc) More -> L(NodeA Same lc y rc) Less -> rotl lc y rc -- rebalance Note the rotations in red

Example code The rest is in the accompanying Haskell file data (+) a b = L a | R b rotr :: Avl(Succ(Succ n)) -> Int -> Avl n -> (Avl(Succ(Succ n))+Avl(Succ(Succ(Succ n)))) -- rotr Tip u a = unreachable rotr (NodeA Same b v c) u a = R(NodeA Less b v (NodeA More c u a)) rotr (NodeA More b v c) u a = L(NodeA Same b v (NodeA Same c u a)) -- rotr (NodeA Less b v TipA) u a = unreachable rotr (NodeA Less b v (NodeA Same x m y)) u a = L(NodeA Same (NodeA Same b v x) m (NodeA Same y u a)) rotr (NodeA Less b v (NodeA Less x m y)) u a = L(NodeA Same (NodeA More b v x) m (NodeA Same y u a)) rotr (NodeA Less b v (NodeA More x m y)) u a = L(NodeA Same (NodeA Same b v x) m (NodeA Less y u a))

At the top level Insertion may make the height of the tree grow. Hide the height of the tree as an existentially quantified index. data AVL = forall h. AVL (Avl h)

2-3-Tree a tree where every node with children (internal node) has either two children (2-node) and one data element or three children (3- nodes) and two data elements. Nodes on the outside of the tree (leaf nodes) have no children and zero, one or two data elements data Tree23:: Nat -> * -> * where Three :: (Tree23 n a) -> a -> (Tree23 n a) -> a -> (Tree23 (Succ n) a) Two:: (Tree23 n a) -> a -> (Tree23 n a) -> (Tree23 (Succ n) a) Leaf1 :: a -> (Tree23 Zero a) Leaf2 :: a -> a -> (Tree23 Zero a) Leaf0 :: (Tree23 Zero a)

Witnessing equality Sometimes we need to prove that two types are equal. We need a type that represents this proposition. We call this a witness, since legal terms with this type only witness that the two types are the same. This is sometimes called provable equality (since it is possible to write a function that returns an element of this type). data Equal:: k -> k -> * where Refl :: Equal x x

Representation types data Rep:: * -> * where Int:: Rep Int Char:: Rep Char Float:: Rep Float Bool :: Rep Bool Pair:: Rep a -> Rep b -> Rep (a,b) List :: Rep a -> Rep [a] Some times this is called a Universe, since it witnesses only those types representable.

Generic Programming eq:: Rep a -> a -> a -> Bool eq Int x y = x==y eq Char x y = x==y eq Float x y = x==y eq Bool x y = x==y eq (Pair t1 t2)(a,b) (c,d) = (eq t1 a c) && (eq t2 b d) eq (List t) xs ys | not(length xs == length ys) = False | otherwise = and (zipWith (eq t) xs ys)

Using provable equality We need a program to inspect two Rep types (at runtime) to possible produce a proof that the types that they represent are the same. test:: Rep a -> Rep b -> Maybe(Equal a b) This is sort of like an equality test, but reflects in its type that the two types are really equal.

Code for test test:: Rep a -> Rep b -> Maybe(Equal a b) test Int Int = Just Refl test Char Char = Just Refl test Float Float = Just Refl test Bool Bool = Just Refl test (Pair x y) (Pair m n) = do { Refl <- test x m ; Refl <- test y n ; Just Refl } test (List x) (List y) = do { Refl <- test x y ; Just Refl} test _ _ = Nothing When we pattern match against Refl, the compiler know that the two types are statically equal in the scope of the match.

Well typed terms data Exp:: * -> * where IntE :: Int -> Exp Int CharE:: Char -> Exp Char PairE :: Exp a -> Exp b -> Exp (a,b) VarE:: String -> Rep t -> Exp t LamE:: String -> Rep t -> Exp s -> Exp (t -> s) ApplyE:: Exp (a -> b) -> Exp a -> Exp b FstE:: Exp(a,b) -> Exp a SndE:: Exp(a,b) -> Exp b

Typing judgements Well typed terms have the exact same structure as a typing judgment. Consider the constructor ApplyE ApplyE:: Exp (a -> b) -> Exp a -> Exp b Compare it to the typing judgement

Tagless interpreter An interpreter gives a value to a term. Usually we need to invent a value datatype like data Value = IntV Int | FunV (Value -> Value) | PairV Value Value We also need to store Values in an environment – data Env = E [(String,Value)]

Valueless environments data Env where Empty :: Env Extend :: String -> Rep t -> t -> Env -> Env Note that the type variable “t” is existentially quantified. Given a pattern ( Extend var rep t more ) There is not much we can do with t, since we do not know its type.

Tagless interpreter eval:: Exp t -> Env -> t eval (IntE n) env = n eval (CharE c) env = c eval (PairE x y) env = (eval x env, eval y env) eval (VarE s t) Empty = error ("Variable not found: "++s) eval (LamE nm t body) env = (\ v -> eval body (Extend nm t v env)) eval (ApplyE f x) env = (eval f env) (eval x env) eval (FstE x) env = fst(eval x env) eval (SndE x) env = snd(eval x env) eval s t1)) (Extend nm t2 value more) | s==nm = case test t1 t2 of Just Refl -> value Nothing -> error "types don't match" | otherwise = eval v more

Units of measure data TempUnit = Fahrenheit | Celsius | Kelvin data Degree:: TempUnit -> * where F:: Float -> Degree Fahrenheit C:: Float -> Degree Celsius K:: Float -> Degree Kelvin add:: Degree u -> Degree u -> Degree u add (F x) (F y) = F(x+y) add (C x) (C y) = C(x+y) add (K x) (K y) = K(x+y)

N-way zip zipN 1 (+1) [1,2,3]  [2,3,4] zipN 2 (+) [1,2,3] [4,5,6]  [5,7,9] zipN 3 (\ x y z -> (x+z,y))[2,3] [5,1] [6,8]  [(8,5),(11,1)]

The Natural Numbers with strange types data Zip :: * -> * -> * where Z:: Zip a [a] S:: Zip b c -> Zip (a -> b) ([a] -> c) Z :: Zip a [a] (S Z) :: Zip (a -> b) ([a] -> [b]) (S (S Z)) :: Zip (a -> a1 -> b) ([a] -> [a1] -> [b]) (S(S (S Z))) :: Zip (a -> a1 -> a2 -> b) ([a] -> [a1] -> [a2] -> [b])

Why these types. f :: (a -> b -> c -> d) (f x) :: (b -> c -> d) (f x y) :: (c -> d) (f x y z) :: d (zip f) :: ([a] -> [b] -> [c] -> [d]) (zip f xs) :: ([b] -> [c] -> [d]) (zip f xs ys) :: ([c] -> [d]) (zip f xs ys za) :: [d]

zero’ = Z one’ = S Z two’ = S (S Z) help:: Zip a b -> a -> b -> b help Z x xs = x:xs help (S n) f rcall = (\ ys -> case ys of (z:zs) -> help n (f z) (rcall zs) other -> skip n)

Code skip:: Zip a b -> b skip Z = [] skip (S n) = \ ys -> skip n zipN:: Zip a b -> a -> b zipN Z = \ n -> [n] zipN m)) = let zip f = help n f (\ x -> zip f x) in zip