SlideShare a Scribd company logo
REFINED TYPES 
DOM DE RE 
FP-SYD, 24 SEPT, 2014
PARTIALITY
It starts off so innocently: 
head' :: [a] -> a 
head' (x : _) = x 
head' [] = undefined 
tail' :: [a] -> [a] 
tail' (_ : xs) = xs 
tail' [] = undefined
WHATS THE 
PROBLEM? 
"Just don't give it an empty list." - Some Pragmatic 
Programmer
THE RABBIT 
HOLE
First we learn about Maybe, adulterate the type to add a rug 
to sweep the unwanted kernel under. 
head' :: [a] -> Maybe a 
head' (x : _) = Just x 
head' [] = Nothing 
tail' :: [a] -> Maybe [a] 
tail' (_ : xs) = Just xs 
tail' [] = Nothing
We have abstractions to propagate things like Maybe to the 
end of the control flow: 
class Functor f where 
fmap :: (a -> b) -> f a -> f b 
class (Functor f) => Applicative f where 
pure :: a -> f a 
(<*>) :: f (a -> b) -> f a -> f b 
liftA2 
:: (Applicative f) 
=> (a -> b -> c) 
-> f a -> f b -> f c 
class Monad m where 
return :: a -> m a 
(>>=) :: m a -> (a -> m b) -> m b
But this is just a case of an unwanted pattern, rather than 
adulterate the output type, we could refine the input type: 
data NonEmpty a = a :| [a] 
nonEmpty :: [a] -> Maybe (NonEmpty a) 
nonEmpty (x : xs) = Just $ x :| xs 
nonEmpty [] = Nothing 
head' :: NonEmpty a -> a 
head' (x :| _) = x 
tail' :: NonEmpty a -> [a] 
tail' (_ :| xs) = xs
FUNCTOR 
And using the same machinery we can lift these simpler 
total functions up to the more complicated types: 
headl :: [a] -> Maybe a 
headl = fmap head' . nonEmpty 
taill :: [a] -> Maybe [a] 
taill = fmap tail' . nonEmpty
APPLICATIVE 
liftA2 
:: (Applicative f) 
=> (a -> b -> c) 
-> f a -> f b -> f c
MONAD 
(=<<) 
:: (Monad m) 
=> (a -> m b) 
-> m a -> m b
LENS & 
TRAVERSALS 
fromList :: [a] -> Either [b] (NonEmpty a) 
fromList = maybe (Left []) Right . nonEmpty 
toList :: NonEmpty a -> [a] 
toList (x :| xs) = x : xs 
_NonEmpty :: Prism [a] [b] (NonEmpty a) (NonEmpty b) 
_NonEmpty = prism toList fromList 
dropTail :: NonEmpty a -> NonEmpty a 
dropTail (x :| _) = x :| [] 
-- Provided you are happy with the "do nothing" response 
-- for values in the kernel of fromList 
over _NonEmpty 
:: (NonEmpty a -> NonEmpty b) 
-> [a] -> [b]
SO.... 
We have a lot of tools to lift functions on simpler types into 
functions on more complex types. 
This all sounds great, so where does it go wrong?
ROCK BOTTOM
A BINARY TREE 
data Tree a = 
Leaf 
| Node a (Tree a) (Tree a)
RED-BLACK 
TREE 
data Colour = Red | Black 
data RBTree a = 
Leaf 
| Node Colour a (RBTree a) (RBTree a)
OH WAIT! 
Invariants: 
1. Red nodes have no Red Children 
2. All paths from the root node to the leaves have the same 
number of black nodes
PROPERTIES 
This is a common use for properties, write up your 
properties that check that the invariants are valid in the 
output. 
Write up your Arbitrary instance for your type that 
produces values that satisfy the invariant.
Sometimes, writing up code that generates the invariant 
satisfying values ends up being very similar to the code 
you are testing... 
On top of that concern, you have to worry about the 
coverage of the invariant satisfying subset.
insert 
:: (Ord a) 
=> a 
-> RBTree a 
-> RBTree a 
balance 
:: Colour 
-> a 
-> RBTree a 
-> RBTree a 
-> RBTree a
LET'S REFINE 
data Colour = Red | Black 
data RBTree a = 
Leaf 
| Node Colour a (RBTree a) (RBTree a)
BAM! 
-- Ignoring Invariant 2 since we only looking at inserts 
data RedNode a = RedNode a (BlackNode a) (BlackNode a) 
-- technically, the root node is supposed to be black, so this would 
-- represent a red black tree in its final state. 
data BlackNode a = 
Leaf 
| BlackNode a (RedBlack a) (RedBlack a) 
data RedBlack a = R (RedNode a) | B (BlackNode a)
Oh, and while we are inserting a value into the tree, the tree 
can be in an intermediate state where Invariant 1 is broken 
at the root: 
-- This is assumed to be representing a Red Node 
-- at the root 
data Invariant1Broken a = 
LeftRedChild a (RedNode a) (BlackNode a) 
| RightRedChild a (BlackNode a) (RedNode a) 
data InsertState a = 
Ok (RedBlack a) 
| Broken (Invariant1Broken a)
Wooo! Alright, now lets go rewrite those two simple yet 
incredibly bug prone functions!
BEFORE 
insert 
:: (Ord a) 
=> a 
-> RBTree a 
-> RBTree a 
balance 
:: Colour 
-> a 
-> RBTree a 
-> RBTree a 
-> RBTree a
AFTER 
balanceblackl :: a -> InsertState a -> RedBlack a -> RedBlack a 
balanceblackr :: a -> RedBlack a -> InsertState a -> RedBlack a 
fixBroken :: InsertState a -> BlackNode a 
ins :: (Ord a) => a -> RedBlack a -> InsertState a 
insBlack :: (Ord a) => a -> BlackNode a -> RedBlack a 
insRed :: (Ord a) => a -> RedNode a -> InsertState a 
joinRedl :: a -> RedBlack a -> BlackNode a -> InsertState a 
joinRedr :: a -> BlackNode a -> RedBlack a -> InsertState a 
insert :: (Ord a) => a -> BlackNode a -> BlackNode a
When the compiler finally released me I had realised I hadn't 
eaten for 5 days. 
But I don't have a problem.
The Rabbit hole goes further with Invariant 2 and deletes, 
with DataKinds or GADTs. 
The deletes involve leaving the tree in an intermediate 
state where invariant 2 is broken. 
Not going there in this talk.
REFLECTION
So whats the problem here? 
What's the difference between the [a] / NonEmpty a case?
All of the types could be injected into RBTree a much like 
NonEmpty a can be injected into [a]. 
But theres a conceivable use for [a], values exist. 
Other than implementing the core operations, users of 
the of the data structure should never encounter values 
that break the invariants.
REFINING TYPES 
So far when I "refined" a type, I had to write up a 
completely new distinct type. 
Conversions between all these different types can be 
potentially inefficient. 
To "refine" [a], had to throw away the [] and build 
NonEmpty a from a again.
We almost always use Type constructors to adulterate types 
(except for Const and Identity)
So could we get more mileage from our types if we could 
qualify our types to restrict or refine them instead of 
adulterating them?
type RedNode a = { t : RBTree a | ??? } 
type BlackNode a = { t : RBTree a | ??? } 
type RedBlack a = { t : RBTree a | ??? } 
type InsertState a = { t : RBTree a | ??? }
LIQUID 
HASKELL
A WORKED 
EXAMPLE
RED-BLACK 
TREES?
Haha, goodness me no. 
You can see my very very very early attempt at using 
DataKinds and GADTs to do it here 
And a recent experiment with Liquid Types that doesn't 
quite work yet here.
BINOMIAL 
TREES 
A primitive from which Binomial heaps are built: 
data BinomialTree a = BinomialTree a [a] 
Defined inductively as follows: 
Binomial tree of Rank 0 is a singleton node. 
A binomial tree of rank r + 1 is formed by linking two 
binomial trees of rank r, with one becoming a child of the 
other.
MEASURES 
Liquid Haskell lets you define simple functions to use in 
constraints. They can't return functions though. 
{-@ 
measure binTreeRank :: BinomialTree a -> Int 
binTreeRank (BinomialTree x cs) = len cs 
@-}
REFINED TYPES 
Or Liquid Types (Logically Qualified Data Types). 
Similar to Subset Types in Coq. 
{-@ type BinomialTreeN a N = {t : BinomialTree a | (binTreeRank t) = N} @-}
INVARIANTS 
The inductive definition results in the following invariant: 
The list of children is ordered by decreasing rank, with 
each element 1 rank higher than the next...
Encode invariants into the type: 
data BinomialTreeList a = 
Nil 
| Cons (BinomialTreeList a) (BinomialTree a) 
{-@ 
measure listlen :: BinomialTreeList a -> Int 
listlen (Nil) = 0 
listlen (Cons xs x) = 1 + (listlen xs) 
@-} 
{-@ invariant {v : BinomialTreeList a | (listlen v) >= 0} @-} 
{-@ 
type BinomialTreeListN a N = {ts : BinomialTreeList a | (listlen ts) = N} 
@-} 
-- Invariant here 
{-@ 
data BinomialTreeList [listlen] a = 
Nil 
| Cons (ts :: BinomialTreeList a) 
(t :: BinomialTreeListN a {(listlen ts)}) 
@-}
Let's store the rank in the structure and add an invariant for 
that also: 
data BinomialTree a = BinomialTree Int a (BinomialTreeList a) 
{-@ 
measure binTreeRank :: BinomialTree a -> Int 
binTreeRank (BinomialTree r x cs) = r 
@-} 
{-@ 
data BinomialTree a = 
BinomialTree (r :: Int) (x :: a) (cs :: BinomialTreeListN a {r}) 
@-}
Can now provide guarantees on the outputs of functions 
that are statically checked: 
{-@ binlength :: t : BinomialTreeList a -> {x : Int | x = (listlen t)} @-} 
binlength :: BinomialTreeList a -> Int 
binlength Nil = 0 
binlength (Cons ts _) = 1 + binlength ts 
{-@ rank :: v : BinomialTree a -> {x : Int | x = (binTreeRank v)} @-} 
rank :: BinomialTree a -> Int 
rank (BinomialTree r _ _) = r 
-- rank (BinomialTree _ _ cs) = binlength cs 
-- rank _ = 0
Verify the inductive definition is preserved by our 
implementation of the core operations: 
-- | Singleton node defined to have rank 0 
{-@ singletonTree :: a -> BinomialTreeN a {0} @-} 
singletonTree :: a -> BinomialTree a 
singletonTree x = BinomialTree 0 x Nil 
-- | Rank r + 1 tree is created by linking together two rank r trees. 
{-@ 
link 
:: (Ord a) 
=> w : BinomialTree a 
-> z : BinomialTreeN a {(binTreeRank w)} 
-> BinomialTreeN a {1 + (binTreeRank w)} 
@-} 
link :: BinomialTree a -> BinomialTree a -> BinomialTree a 
link w@(BinomialTree rw x ws) z@(BinomialTree rz y zs) 
| x < y = BinomialTree (rw + 1) x (Cons ws z) 
| otherwise = BinomialTree (rz + 1) y (Cons zs w)
FINAL 
THOUGHTS
PROS 
Don't have to manipulate proofs in parallel with program 
values. 
Some of the expressive capacity of Dependent Types
LIMITATIONS 1 
Only some of the expressive capacity of Dependent Types 
Can use any SMT solver backend apparently, but z3 is the 
only with a reliable enough reputation 
z3 is not free (Non-Commercial Research use only) 
Using an SMT solver is a little "black boxy", not sure I 
would ever want it in the compiler, don't know if that will 
ever take off 
Then again, I didn't think the IPod was going to be a big 
deal.
LIMITATIONS 2 
If refined types rule out specific patterns (e.g Red Black 
trees), fails exhaustivity checking in GHC since the 
function is effectively partial as far as GHC is concerned. 
A lot of the time, expressing 
properties/invariants/constraints is really just as 
challenging as doing so in the existing type system. 
So I don't think we have solved the Type complexity 
problem yet. 
At the moment its like a separate type system running in 
parallel, gets a little schizophrenic. 
Terrible error messages
{-@ binlength :: t : BinomialTreeList a -> {x : Int | x = (listlen t)} @-} 
binlength :: BinomialTreeList a -> Int 
binlength Nil = 0 
binlength (Cons ts _) = 2 + binlength ts 
src/Data/Binomial.hs:75:26-41: Error: Liquid Type Mismatch 
Inferred type 
VV : Int | (VV == (?c + ?a)) 
not a subtype of Required type 
VV : Int | (VV == (listlen ?b)) 
In Context 
ts : (BinomialTreeList a) | ((listlen ts) >= 0) 
?b : (BinomialTreeList a) | ((listlen ?b) >= 0) 
?a : Int | (?a == (listlen ts)) 
?c : Int | (?c == (2 : int))
REFERENCES 
AND FURTHER 
READING 
Z3 
N. Vazou, E. L. Seidel, R. Jhala, D. Vytiniotis, and S. Peyton- 
Jones. Refinement types for Haskell 
Try Liquid Haskell - An Online Interactive Liquid Haskell 
Demo

More Related Content

What's hot

Scala collections
Scala collectionsScala collections
Scala collections
Inphina Technologies
 
Zippers
ZippersZippers
Zippers
David Overton
 
High-Performance Haskell
High-Performance HaskellHigh-Performance Haskell
High-Performance Haskell
Johan Tibell
 
Why Haskell Matters
Why Haskell MattersWhy Haskell Matters
Why Haskell Matters
romanandreg
 
Constraint Programming in Haskell
Constraint Programming in HaskellConstraint Programming in Haskell
Constraint Programming in Haskell
David Overton
 
Haskell for data science
Haskell for data scienceHaskell for data science
Haskell for data science
John Cant
 
Scala parallel-collections
Scala parallel-collectionsScala parallel-collections
Scala parallel-collections
Knoldus Inc.
 
Functional programming with_scala
Functional programming with_scalaFunctional programming with_scala
Functional programming with_scala
Raymond Tay
 
Comonads in Haskell
Comonads in HaskellComonads in Haskell
Comonads in Haskell
David Overton
 
N-Queens Combinatorial Problem - Polyglot FP for Fun and Profit – Haskell and...
N-Queens Combinatorial Problem - Polyglot FP for Fun and Profit – Haskell and...N-Queens Combinatorial Problem - Polyglot FP for Fun and Profit – Haskell and...
N-Queens Combinatorial Problem - Polyglot FP for Fun and Profit – Haskell and...
Philip Schwarz
 
N-Queens Combinatorial Problem - Polyglot FP for Fun and Profit - Haskell and...
N-Queens Combinatorial Problem - Polyglot FP for Fun and Profit - Haskell and...N-Queens Combinatorial Problem - Polyglot FP for Fun and Profit - Haskell and...
N-Queens Combinatorial Problem - Polyglot FP for Fun and Profit - Haskell and...
Philip Schwarz
 
Functions In Scala
Functions In Scala Functions In Scala
Functions In Scala
Knoldus Inc.
 
Data analysis with R
Data analysis with RData analysis with R
Data analysis with R
ShareThis
 
Data Analysis and Programming in R
Data Analysis and Programming in RData Analysis and Programming in R
Data Analysis and Programming in R
Eshwar Sai
 
Introduction to haskell
Introduction to haskellIntroduction to haskell
Introduction to haskell
Luca Molteni
 
Array
ArrayArray
Scala Bootcamp 1
Scala Bootcamp 1Scala Bootcamp 1
Scala Bootcamp 1
Knoldus Inc.
 
Pandas Series
Pandas SeriesPandas Series
Pandas Series
Sangita Panchal
 
Frp2016 3
Frp2016 3Frp2016 3
Frp2016 3
Kirill Kozlov
 

What's hot (19)

Scala collections
Scala collectionsScala collections
Scala collections
 
Zippers
ZippersZippers
Zippers
 
High-Performance Haskell
High-Performance HaskellHigh-Performance Haskell
High-Performance Haskell
 
Why Haskell Matters
Why Haskell MattersWhy Haskell Matters
Why Haskell Matters
 
Constraint Programming in Haskell
Constraint Programming in HaskellConstraint Programming in Haskell
Constraint Programming in Haskell
 
Haskell for data science
Haskell for data scienceHaskell for data science
Haskell for data science
 
Scala parallel-collections
Scala parallel-collectionsScala parallel-collections
Scala parallel-collections
 
Functional programming with_scala
Functional programming with_scalaFunctional programming with_scala
Functional programming with_scala
 
Comonads in Haskell
Comonads in HaskellComonads in Haskell
Comonads in Haskell
 
N-Queens Combinatorial Problem - Polyglot FP for Fun and Profit – Haskell and...
N-Queens Combinatorial Problem - Polyglot FP for Fun and Profit – Haskell and...N-Queens Combinatorial Problem - Polyglot FP for Fun and Profit – Haskell and...
N-Queens Combinatorial Problem - Polyglot FP for Fun and Profit – Haskell and...
 
N-Queens Combinatorial Problem - Polyglot FP for Fun and Profit - Haskell and...
N-Queens Combinatorial Problem - Polyglot FP for Fun and Profit - Haskell and...N-Queens Combinatorial Problem - Polyglot FP for Fun and Profit - Haskell and...
N-Queens Combinatorial Problem - Polyglot FP for Fun and Profit - Haskell and...
 
Functions In Scala
Functions In Scala Functions In Scala
Functions In Scala
 
Data analysis with R
Data analysis with RData analysis with R
Data analysis with R
 
Data Analysis and Programming in R
Data Analysis and Programming in RData Analysis and Programming in R
Data Analysis and Programming in R
 
Introduction to haskell
Introduction to haskellIntroduction to haskell
Introduction to haskell
 
Array
ArrayArray
Array
 
Scala Bootcamp 1
Scala Bootcamp 1Scala Bootcamp 1
Scala Bootcamp 1
 
Pandas Series
Pandas SeriesPandas Series
Pandas Series
 
Frp2016 3
Frp2016 3Frp2016 3
Frp2016 3
 

Viewers also liked

2014 09 mandatum dubnikovas
2014 09 mandatum dubnikovas2014 09 mandatum dubnikovas
2014 09 mandatum dubnikovas
Investuok
 
Krize 9
Krize 9Krize 9
Krize 9
Investuok
 
SEM15042 Celiešius
SEM15042 CeliešiusSEM15042 Celiešius
SEM15042 Celiešius
Investuok
 
SEM15041 Dubnikovas
SEM15041 DubnikovasSEM15041 Dubnikovas
SEM15041 DubnikovasInvestuok
 
2014 12 baltijos saliu akciju rinku prognozes 2015 investuok
2014 12 baltijos saliu akciju rinku prognozes 2015 investuok2014 12 baltijos saliu akciju rinku prognozes 2015 investuok
2014 12 baltijos saliu akciju rinku prognozes 2015 investuok
Investuok
 
2015 01 turtėjimo pagrindai kaunas.
2015 01 turtėjimo pagrindai   kaunas.2015 01 turtėjimo pagrindai   kaunas.
2015 01 turtėjimo pagrindai kaunas.
Investuok
 
krize 5
krize 5krize 5
krize 5
Investuok
 
2015 06 pranesimas.investavimo i nt formos.2015 06-16
2015 06 pranesimas.investavimo i nt formos.2015 06-162015 06 pranesimas.investavimo i nt formos.2015 06-16
2015 06 pranesimas.investavimo i nt formos.2015 06-16
Investuok
 
2015 09 invstuok apie baltija
2015 09 invstuok apie baltija2015 09 invstuok apie baltija
2015 09 invstuok apie baltija
Investuok
 
2015 06 17 investuok
2015 06 17 investuok2015 06 17 investuok
2015 06 17 investuok
Investuok
 
krize 4
krize 4krize 4
krize 4
Investuok
 
2015 06 investuo kprezentacija
2015 06 investuo kprezentacija2015 06 investuo kprezentacija
2015 06 investuo kprezentacija
Investuok
 
2014.12.17 pasaulio ekonomika mauricas
2014.12.17 pasaulio ekonomika mauricas2014.12.17 pasaulio ekonomika mauricas
2014.12.17 pasaulio ekonomika mauricas
Investuok
 
2014 12 oh vz nt_rinka_2014_gruodis_final
2014 12 oh vz nt_rinka_2014_gruodis_final2014 12 oh vz nt_rinka_2014_gruodis_final
2014 12 oh vz nt_rinka_2014_gruodis_final
Investuok
 
krize 2
krize 2krize 2
krize 2
Investuok
 
Krize1
Krize1Krize1
Krize1
Investuok
 
krize 6 1
krize 6 1krize 6 1
krize 6 1
Investuok
 
krize 6 2
krize 6 2krize 6 2
krize 6 2
Investuok
 
2014 09 baltijos rinka vaidotas rukas
2014 09 baltijos rinka vaidotas rukas2014 09 baltijos rinka vaidotas rukas
2014 09 baltijos rinka vaidotas rukas
Investuok
 
Archives à conserver Associations loi 1901 .compressed 1
Archives à conserver Associations loi 1901 .compressed 1Archives à conserver Associations loi 1901 .compressed 1
Archives à conserver Associations loi 1901 .compressed 1
Dominique Gayraud
 

Viewers also liked (20)

2014 09 mandatum dubnikovas
2014 09 mandatum dubnikovas2014 09 mandatum dubnikovas
2014 09 mandatum dubnikovas
 
Krize 9
Krize 9Krize 9
Krize 9
 
SEM15042 Celiešius
SEM15042 CeliešiusSEM15042 Celiešius
SEM15042 Celiešius
 
SEM15041 Dubnikovas
SEM15041 DubnikovasSEM15041 Dubnikovas
SEM15041 Dubnikovas
 
2014 12 baltijos saliu akciju rinku prognozes 2015 investuok
2014 12 baltijos saliu akciju rinku prognozes 2015 investuok2014 12 baltijos saliu akciju rinku prognozes 2015 investuok
2014 12 baltijos saliu akciju rinku prognozes 2015 investuok
 
2015 01 turtėjimo pagrindai kaunas.
2015 01 turtėjimo pagrindai   kaunas.2015 01 turtėjimo pagrindai   kaunas.
2015 01 turtėjimo pagrindai kaunas.
 
krize 5
krize 5krize 5
krize 5
 
2015 06 pranesimas.investavimo i nt formos.2015 06-16
2015 06 pranesimas.investavimo i nt formos.2015 06-162015 06 pranesimas.investavimo i nt formos.2015 06-16
2015 06 pranesimas.investavimo i nt formos.2015 06-16
 
2015 09 invstuok apie baltija
2015 09 invstuok apie baltija2015 09 invstuok apie baltija
2015 09 invstuok apie baltija
 
2015 06 17 investuok
2015 06 17 investuok2015 06 17 investuok
2015 06 17 investuok
 
krize 4
krize 4krize 4
krize 4
 
2015 06 investuo kprezentacija
2015 06 investuo kprezentacija2015 06 investuo kprezentacija
2015 06 investuo kprezentacija
 
2014.12.17 pasaulio ekonomika mauricas
2014.12.17 pasaulio ekonomika mauricas2014.12.17 pasaulio ekonomika mauricas
2014.12.17 pasaulio ekonomika mauricas
 
2014 12 oh vz nt_rinka_2014_gruodis_final
2014 12 oh vz nt_rinka_2014_gruodis_final2014 12 oh vz nt_rinka_2014_gruodis_final
2014 12 oh vz nt_rinka_2014_gruodis_final
 
krize 2
krize 2krize 2
krize 2
 
Krize1
Krize1Krize1
Krize1
 
krize 6 1
krize 6 1krize 6 1
krize 6 1
 
krize 6 2
krize 6 2krize 6 2
krize 6 2
 
2014 09 baltijos rinka vaidotas rukas
2014 09 baltijos rinka vaidotas rukas2014 09 baltijos rinka vaidotas rukas
2014 09 baltijos rinka vaidotas rukas
 
Archives à conserver Associations loi 1901 .compressed 1
Archives à conserver Associations loi 1901 .compressed 1Archives à conserver Associations loi 1901 .compressed 1
Archives à conserver Associations loi 1901 .compressed 1
 

Similar to Refined types (FP-Syd)

PYTHON ALGORITHMS, DATA STRUCTURE, SORTING TECHNIQUES
PYTHON ALGORITHMS, DATA STRUCTURE, SORTING TECHNIQUESPYTHON ALGORITHMS, DATA STRUCTURE, SORTING TECHNIQUES
PYTHON ALGORITHMS, DATA STRUCTURE, SORTING TECHNIQUES
vanithasivdc
 
Introduction to idris
Introduction to idrisIntroduction to idris
Introduction to idris
Conor Farrell
 
Reasoning about laziness
Reasoning about lazinessReasoning about laziness
Reasoning about laziness
Johan Tibell
 
Real World Haskell: Lecture 5
Real World Haskell: Lecture 5Real World Haskell: Lecture 5
Real World Haskell: Lecture 5
Bryan O'Sullivan
 
Data Wrangling with Pandas
Data Wrangling with PandasData Wrangling with Pandas
Data Wrangling with Pandas
Luis Carrasco
 
Pandas cheat sheet_data science
Pandas cheat sheet_data sciencePandas cheat sheet_data science
Pandas cheat sheet_data science
Subrata Shaw
 
Pandas Cheat Sheet
Pandas Cheat SheetPandas Cheat Sheet
Pandas Cheat Sheet
ACASH1011
 
Pandas cheat sheet
Pandas cheat sheetPandas cheat sheet
Pandas cheat sheet
Lenis Carolina Lopez
 
CS-102 BST_27_3_14v2.pdf
CS-102 BST_27_3_14v2.pdfCS-102 BST_27_3_14v2.pdf
CS-102 BST_27_3_14v2.pdf
ssuser034ce1
 
Wheels we didn't re-invent: Perl's Utility Modules
Wheels we didn't re-invent: Perl's Utility ModulesWheels we didn't re-invent: Perl's Utility Modules
Wheels we didn't re-invent: Perl's Utility Modules
Workhorse Computing
 
Dancing Links: an educational pearl
Dancing Links: an educational pearlDancing Links: an educational pearl
Dancing Links: an educational pearl
ESUG
 
Data Wrangling with dplyr and tidyr Cheat Sheet
Data Wrangling with dplyr and tidyr Cheat SheetData Wrangling with dplyr and tidyr Cheat Sheet
Data Wrangling with dplyr and tidyr Cheat Sheet
Dr. Volkan OBAN
 
Data transformation-cheatsheet
Data transformation-cheatsheetData transformation-cheatsheet
Data transformation-cheatsheet
Dieudonne Nahigombeye
 
dynamic programming Rod cutting class
dynamic programming Rod cutting classdynamic programming Rod cutting class
dynamic programming Rod cutting class
giridaroori
 
Review session2
Review session2Review session2
Review session2
NEEDY12345
 
Morel, a Functional Query Language
Morel, a Functional Query LanguageMorel, a Functional Query Language
Morel, a Functional Query Language
Julian Hyde
 
R gráfico
R gráficoR gráfico
R gráfico
stryper1968
 
C++ ProgramRecursive reversal of a tree.[16] Write a method voi.pdf
C++ ProgramRecursive reversal of a tree.[16] Write a method voi.pdfC++ ProgramRecursive reversal of a tree.[16] Write a method voi.pdf
C++ ProgramRecursive reversal of a tree.[16] Write a method voi.pdf
funkybabyindia
 
16 rbtrees
16 rbtrees16 rbtrees
16 rbtrees
Dheeraj Singh
 
Recursion Lecture in Java
Recursion Lecture in JavaRecursion Lecture in Java
Recursion Lecture in Java
Raffi Khatchadourian
 

Similar to Refined types (FP-Syd) (20)

PYTHON ALGORITHMS, DATA STRUCTURE, SORTING TECHNIQUES
PYTHON ALGORITHMS, DATA STRUCTURE, SORTING TECHNIQUESPYTHON ALGORITHMS, DATA STRUCTURE, SORTING TECHNIQUES
PYTHON ALGORITHMS, DATA STRUCTURE, SORTING TECHNIQUES
 
Introduction to idris
Introduction to idrisIntroduction to idris
Introduction to idris
 
Reasoning about laziness
Reasoning about lazinessReasoning about laziness
Reasoning about laziness
 
Real World Haskell: Lecture 5
Real World Haskell: Lecture 5Real World Haskell: Lecture 5
Real World Haskell: Lecture 5
 
Data Wrangling with Pandas
Data Wrangling with PandasData Wrangling with Pandas
Data Wrangling with Pandas
 
Pandas cheat sheet_data science
Pandas cheat sheet_data sciencePandas cheat sheet_data science
Pandas cheat sheet_data science
 
Pandas Cheat Sheet
Pandas Cheat SheetPandas Cheat Sheet
Pandas Cheat Sheet
 
Pandas cheat sheet
Pandas cheat sheetPandas cheat sheet
Pandas cheat sheet
 
CS-102 BST_27_3_14v2.pdf
CS-102 BST_27_3_14v2.pdfCS-102 BST_27_3_14v2.pdf
CS-102 BST_27_3_14v2.pdf
 
Wheels we didn't re-invent: Perl's Utility Modules
Wheels we didn't re-invent: Perl's Utility ModulesWheels we didn't re-invent: Perl's Utility Modules
Wheels we didn't re-invent: Perl's Utility Modules
 
Dancing Links: an educational pearl
Dancing Links: an educational pearlDancing Links: an educational pearl
Dancing Links: an educational pearl
 
Data Wrangling with dplyr and tidyr Cheat Sheet
Data Wrangling with dplyr and tidyr Cheat SheetData Wrangling with dplyr and tidyr Cheat Sheet
Data Wrangling with dplyr and tidyr Cheat Sheet
 
Data transformation-cheatsheet
Data transformation-cheatsheetData transformation-cheatsheet
Data transformation-cheatsheet
 
dynamic programming Rod cutting class
dynamic programming Rod cutting classdynamic programming Rod cutting class
dynamic programming Rod cutting class
 
Review session2
Review session2Review session2
Review session2
 
Morel, a Functional Query Language
Morel, a Functional Query LanguageMorel, a Functional Query Language
Morel, a Functional Query Language
 
R gráfico
R gráficoR gráfico
R gráfico
 
C++ ProgramRecursive reversal of a tree.[16] Write a method voi.pdf
C++ ProgramRecursive reversal of a tree.[16] Write a method voi.pdfC++ ProgramRecursive reversal of a tree.[16] Write a method voi.pdf
C++ ProgramRecursive reversal of a tree.[16] Write a method voi.pdf
 
16 rbtrees
16 rbtrees16 rbtrees
16 rbtrees
 
Recursion Lecture in Java
Recursion Lecture in JavaRecursion Lecture in Java
Recursion Lecture in Java
 

Recently uploaded

Transform Your Communication with Cloud-Based IVR Solutions
Transform Your Communication with Cloud-Based IVR SolutionsTransform Your Communication with Cloud-Based IVR Solutions
Transform Your Communication with Cloud-Based IVR Solutions
TheSMSPoint
 
APIs for Browser Automation (MoT Meetup 2024)
APIs for Browser Automation (MoT Meetup 2024)APIs for Browser Automation (MoT Meetup 2024)
APIs for Browser Automation (MoT Meetup 2024)
Boni García
 
Neo4j - Product Vision and Knowledge Graphs - GraphSummit Paris
Neo4j - Product Vision and Knowledge Graphs - GraphSummit ParisNeo4j - Product Vision and Knowledge Graphs - GraphSummit Paris
Neo4j - Product Vision and Knowledge Graphs - GraphSummit Paris
Neo4j
 
LORRAINE ANDREI_LEQUIGAN_HOW TO USE ZOOM
LORRAINE ANDREI_LEQUIGAN_HOW TO USE ZOOMLORRAINE ANDREI_LEQUIGAN_HOW TO USE ZOOM
LORRAINE ANDREI_LEQUIGAN_HOW TO USE ZOOM
lorraineandreiamcidl
 
2024 eCommerceDays Toulouse - Sylius 2.0.pdf
2024 eCommerceDays Toulouse - Sylius 2.0.pdf2024 eCommerceDays Toulouse - Sylius 2.0.pdf
2024 eCommerceDays Toulouse - Sylius 2.0.pdf
Łukasz Chruściel
 
Need for Speed: Removing speed bumps from your Symfony projects ⚡️
Need for Speed: Removing speed bumps from your Symfony projects ⚡️Need for Speed: Removing speed bumps from your Symfony projects ⚡️
Need for Speed: Removing speed bumps from your Symfony projects ⚡️
Łukasz Chruściel
 
Codeigniter VS Cakephp Which is Better for Web Development.pdf
Codeigniter VS Cakephp Which is Better for Web Development.pdfCodeigniter VS Cakephp Which is Better for Web Development.pdf
Codeigniter VS Cakephp Which is Better for Web Development.pdf
Semiosis Software Private Limited
 
Graspan: A Big Data System for Big Code Analysis
Graspan: A Big Data System for Big Code AnalysisGraspan: A Big Data System for Big Code Analysis
Graspan: A Big Data System for Big Code Analysis
Aftab Hussain
 
Energy consumption of Database Management - Florina Jonuzi
Energy consumption of Database Management - Florina JonuziEnergy consumption of Database Management - Florina Jonuzi
Energy consumption of Database Management - Florina Jonuzi
Green Software Development
 
Utilocate provides Smarter, Better, Faster, Safer Locate Ticket Management
Utilocate provides Smarter, Better, Faster, Safer Locate Ticket ManagementUtilocate provides Smarter, Better, Faster, Safer Locate Ticket Management
Utilocate provides Smarter, Better, Faster, Safer Locate Ticket Management
Utilocate
 
ALGIT - Assembly Line for Green IT - Numbers, Data, Facts
ALGIT - Assembly Line for Green IT - Numbers, Data, FactsALGIT - Assembly Line for Green IT - Numbers, Data, Facts
ALGIT - Assembly Line for Green IT - Numbers, Data, Facts
Green Software Development
 
GOING AOT WITH GRAALVM FOR SPRING BOOT (SPRING IO)
GOING AOT WITH GRAALVM FOR  SPRING BOOT (SPRING IO)GOING AOT WITH GRAALVM FOR  SPRING BOOT (SPRING IO)
GOING AOT WITH GRAALVM FOR SPRING BOOT (SPRING IO)
Alina Yurenko
 
LORRAINE ANDREI_LEQUIGAN_HOW TO USE WHATSAPP.pptx
LORRAINE ANDREI_LEQUIGAN_HOW TO USE WHATSAPP.pptxLORRAINE ANDREI_LEQUIGAN_HOW TO USE WHATSAPP.pptx
LORRAINE ANDREI_LEQUIGAN_HOW TO USE WHATSAPP.pptx
lorraineandreiamcidl
 
Neo4j - Product Vision and Knowledge Graphs - GraphSummit Paris
Neo4j - Product Vision and Knowledge Graphs - GraphSummit ParisNeo4j - Product Vision and Knowledge Graphs - GraphSummit Paris
Neo4j - Product Vision and Knowledge Graphs - GraphSummit Paris
Neo4j
 
Using Xen Hypervisor for Functional Safety
Using Xen Hypervisor for Functional SafetyUsing Xen Hypervisor for Functional Safety
Using Xen Hypervisor for Functional Safety
Ayan Halder
 
socradar-q1-2024-aviation-industry-report.pdf
socradar-q1-2024-aviation-industry-report.pdfsocradar-q1-2024-aviation-industry-report.pdf
socradar-q1-2024-aviation-industry-report.pdf
SOCRadar
 
Why Mobile App Regression Testing is Critical for Sustained Success_ A Detail...
Why Mobile App Regression Testing is Critical for Sustained Success_ A Detail...Why Mobile App Regression Testing is Critical for Sustained Success_ A Detail...
Why Mobile App Regression Testing is Critical for Sustained Success_ A Detail...
kalichargn70th171
 
Fundamentals of Programming and Language Processors
Fundamentals of Programming and Language ProcessorsFundamentals of Programming and Language Processors
Fundamentals of Programming and Language Processors
Rakesh Kumar R
 
Top Features to Include in Your Winzo Clone App for Business Growth (4).pptx
Top Features to Include in Your Winzo Clone App for Business Growth (4).pptxTop Features to Include in Your Winzo Clone App for Business Growth (4).pptx
Top Features to Include in Your Winzo Clone App for Business Growth (4).pptx
rickgrimesss22
 
Mobile App Development Company In Noida | Drona Infotech
Mobile App Development Company In Noida | Drona InfotechMobile App Development Company In Noida | Drona Infotech
Mobile App Development Company In Noida | Drona Infotech
Drona Infotech
 

Recently uploaded (20)

Transform Your Communication with Cloud-Based IVR Solutions
Transform Your Communication with Cloud-Based IVR SolutionsTransform Your Communication with Cloud-Based IVR Solutions
Transform Your Communication with Cloud-Based IVR Solutions
 
APIs for Browser Automation (MoT Meetup 2024)
APIs for Browser Automation (MoT Meetup 2024)APIs for Browser Automation (MoT Meetup 2024)
APIs for Browser Automation (MoT Meetup 2024)
 
Neo4j - Product Vision and Knowledge Graphs - GraphSummit Paris
Neo4j - Product Vision and Knowledge Graphs - GraphSummit ParisNeo4j - Product Vision and Knowledge Graphs - GraphSummit Paris
Neo4j - Product Vision and Knowledge Graphs - GraphSummit Paris
 
LORRAINE ANDREI_LEQUIGAN_HOW TO USE ZOOM
LORRAINE ANDREI_LEQUIGAN_HOW TO USE ZOOMLORRAINE ANDREI_LEQUIGAN_HOW TO USE ZOOM
LORRAINE ANDREI_LEQUIGAN_HOW TO USE ZOOM
 
2024 eCommerceDays Toulouse - Sylius 2.0.pdf
2024 eCommerceDays Toulouse - Sylius 2.0.pdf2024 eCommerceDays Toulouse - Sylius 2.0.pdf
2024 eCommerceDays Toulouse - Sylius 2.0.pdf
 
Need for Speed: Removing speed bumps from your Symfony projects ⚡️
Need for Speed: Removing speed bumps from your Symfony projects ⚡️Need for Speed: Removing speed bumps from your Symfony projects ⚡️
Need for Speed: Removing speed bumps from your Symfony projects ⚡️
 
Codeigniter VS Cakephp Which is Better for Web Development.pdf
Codeigniter VS Cakephp Which is Better for Web Development.pdfCodeigniter VS Cakephp Which is Better for Web Development.pdf
Codeigniter VS Cakephp Which is Better for Web Development.pdf
 
Graspan: A Big Data System for Big Code Analysis
Graspan: A Big Data System for Big Code AnalysisGraspan: A Big Data System for Big Code Analysis
Graspan: A Big Data System for Big Code Analysis
 
Energy consumption of Database Management - Florina Jonuzi
Energy consumption of Database Management - Florina JonuziEnergy consumption of Database Management - Florina Jonuzi
Energy consumption of Database Management - Florina Jonuzi
 
Utilocate provides Smarter, Better, Faster, Safer Locate Ticket Management
Utilocate provides Smarter, Better, Faster, Safer Locate Ticket ManagementUtilocate provides Smarter, Better, Faster, Safer Locate Ticket Management
Utilocate provides Smarter, Better, Faster, Safer Locate Ticket Management
 
ALGIT - Assembly Line for Green IT - Numbers, Data, Facts
ALGIT - Assembly Line for Green IT - Numbers, Data, FactsALGIT - Assembly Line for Green IT - Numbers, Data, Facts
ALGIT - Assembly Line for Green IT - Numbers, Data, Facts
 
GOING AOT WITH GRAALVM FOR SPRING BOOT (SPRING IO)
GOING AOT WITH GRAALVM FOR  SPRING BOOT (SPRING IO)GOING AOT WITH GRAALVM FOR  SPRING BOOT (SPRING IO)
GOING AOT WITH GRAALVM FOR SPRING BOOT (SPRING IO)
 
LORRAINE ANDREI_LEQUIGAN_HOW TO USE WHATSAPP.pptx
LORRAINE ANDREI_LEQUIGAN_HOW TO USE WHATSAPP.pptxLORRAINE ANDREI_LEQUIGAN_HOW TO USE WHATSAPP.pptx
LORRAINE ANDREI_LEQUIGAN_HOW TO USE WHATSAPP.pptx
 
Neo4j - Product Vision and Knowledge Graphs - GraphSummit Paris
Neo4j - Product Vision and Knowledge Graphs - GraphSummit ParisNeo4j - Product Vision and Knowledge Graphs - GraphSummit Paris
Neo4j - Product Vision and Knowledge Graphs - GraphSummit Paris
 
Using Xen Hypervisor for Functional Safety
Using Xen Hypervisor for Functional SafetyUsing Xen Hypervisor for Functional Safety
Using Xen Hypervisor for Functional Safety
 
socradar-q1-2024-aviation-industry-report.pdf
socradar-q1-2024-aviation-industry-report.pdfsocradar-q1-2024-aviation-industry-report.pdf
socradar-q1-2024-aviation-industry-report.pdf
 
Why Mobile App Regression Testing is Critical for Sustained Success_ A Detail...
Why Mobile App Regression Testing is Critical for Sustained Success_ A Detail...Why Mobile App Regression Testing is Critical for Sustained Success_ A Detail...
Why Mobile App Regression Testing is Critical for Sustained Success_ A Detail...
 
Fundamentals of Programming and Language Processors
Fundamentals of Programming and Language ProcessorsFundamentals of Programming and Language Processors
Fundamentals of Programming and Language Processors
 
Top Features to Include in Your Winzo Clone App for Business Growth (4).pptx
Top Features to Include in Your Winzo Clone App for Business Growth (4).pptxTop Features to Include in Your Winzo Clone App for Business Growth (4).pptx
Top Features to Include in Your Winzo Clone App for Business Growth (4).pptx
 
Mobile App Development Company In Noida | Drona Infotech
Mobile App Development Company In Noida | Drona InfotechMobile App Development Company In Noida | Drona Infotech
Mobile App Development Company In Noida | Drona Infotech
 

Refined types (FP-Syd)

  • 1. REFINED TYPES DOM DE RE FP-SYD, 24 SEPT, 2014
  • 3. It starts off so innocently: head' :: [a] -> a head' (x : _) = x head' [] = undefined tail' :: [a] -> [a] tail' (_ : xs) = xs tail' [] = undefined
  • 4. WHATS THE PROBLEM? "Just don't give it an empty list." - Some Pragmatic Programmer
  • 6. First we learn about Maybe, adulterate the type to add a rug to sweep the unwanted kernel under. head' :: [a] -> Maybe a head' (x : _) = Just x head' [] = Nothing tail' :: [a] -> Maybe [a] tail' (_ : xs) = Just xs tail' [] = Nothing
  • 7. We have abstractions to propagate things like Maybe to the end of the control flow: class Functor f where fmap :: (a -> b) -> f a -> f b class (Functor f) => Applicative f where pure :: a -> f a (<*>) :: f (a -> b) -> f a -> f b liftA2 :: (Applicative f) => (a -> b -> c) -> f a -> f b -> f c class Monad m where return :: a -> m a (>>=) :: m a -> (a -> m b) -> m b
  • 8. But this is just a case of an unwanted pattern, rather than adulterate the output type, we could refine the input type: data NonEmpty a = a :| [a] nonEmpty :: [a] -> Maybe (NonEmpty a) nonEmpty (x : xs) = Just $ x :| xs nonEmpty [] = Nothing head' :: NonEmpty a -> a head' (x :| _) = x tail' :: NonEmpty a -> [a] tail' (_ :| xs) = xs
  • 9. FUNCTOR And using the same machinery we can lift these simpler total functions up to the more complicated types: headl :: [a] -> Maybe a headl = fmap head' . nonEmpty taill :: [a] -> Maybe [a] taill = fmap tail' . nonEmpty
  • 10. APPLICATIVE liftA2 :: (Applicative f) => (a -> b -> c) -> f a -> f b -> f c
  • 11. MONAD (=<<) :: (Monad m) => (a -> m b) -> m a -> m b
  • 12. LENS & TRAVERSALS fromList :: [a] -> Either [b] (NonEmpty a) fromList = maybe (Left []) Right . nonEmpty toList :: NonEmpty a -> [a] toList (x :| xs) = x : xs _NonEmpty :: Prism [a] [b] (NonEmpty a) (NonEmpty b) _NonEmpty = prism toList fromList dropTail :: NonEmpty a -> NonEmpty a dropTail (x :| _) = x :| [] -- Provided you are happy with the "do nothing" response -- for values in the kernel of fromList over _NonEmpty :: (NonEmpty a -> NonEmpty b) -> [a] -> [b]
  • 13. SO.... We have a lot of tools to lift functions on simpler types into functions on more complex types. This all sounds great, so where does it go wrong?
  • 15. A BINARY TREE data Tree a = Leaf | Node a (Tree a) (Tree a)
  • 16. RED-BLACK TREE data Colour = Red | Black data RBTree a = Leaf | Node Colour a (RBTree a) (RBTree a)
  • 17. OH WAIT! Invariants: 1. Red nodes have no Red Children 2. All paths from the root node to the leaves have the same number of black nodes
  • 18. PROPERTIES This is a common use for properties, write up your properties that check that the invariants are valid in the output. Write up your Arbitrary instance for your type that produces values that satisfy the invariant.
  • 19. Sometimes, writing up code that generates the invariant satisfying values ends up being very similar to the code you are testing... On top of that concern, you have to worry about the coverage of the invariant satisfying subset.
  • 20. insert :: (Ord a) => a -> RBTree a -> RBTree a balance :: Colour -> a -> RBTree a -> RBTree a -> RBTree a
  • 21. LET'S REFINE data Colour = Red | Black data RBTree a = Leaf | Node Colour a (RBTree a) (RBTree a)
  • 22. BAM! -- Ignoring Invariant 2 since we only looking at inserts data RedNode a = RedNode a (BlackNode a) (BlackNode a) -- technically, the root node is supposed to be black, so this would -- represent a red black tree in its final state. data BlackNode a = Leaf | BlackNode a (RedBlack a) (RedBlack a) data RedBlack a = R (RedNode a) | B (BlackNode a)
  • 23. Oh, and while we are inserting a value into the tree, the tree can be in an intermediate state where Invariant 1 is broken at the root: -- This is assumed to be representing a Red Node -- at the root data Invariant1Broken a = LeftRedChild a (RedNode a) (BlackNode a) | RightRedChild a (BlackNode a) (RedNode a) data InsertState a = Ok (RedBlack a) | Broken (Invariant1Broken a)
  • 24. Wooo! Alright, now lets go rewrite those two simple yet incredibly bug prone functions!
  • 25. BEFORE insert :: (Ord a) => a -> RBTree a -> RBTree a balance :: Colour -> a -> RBTree a -> RBTree a -> RBTree a
  • 26. AFTER balanceblackl :: a -> InsertState a -> RedBlack a -> RedBlack a balanceblackr :: a -> RedBlack a -> InsertState a -> RedBlack a fixBroken :: InsertState a -> BlackNode a ins :: (Ord a) => a -> RedBlack a -> InsertState a insBlack :: (Ord a) => a -> BlackNode a -> RedBlack a insRed :: (Ord a) => a -> RedNode a -> InsertState a joinRedl :: a -> RedBlack a -> BlackNode a -> InsertState a joinRedr :: a -> BlackNode a -> RedBlack a -> InsertState a insert :: (Ord a) => a -> BlackNode a -> BlackNode a
  • 27. When the compiler finally released me I had realised I hadn't eaten for 5 days. But I don't have a problem.
  • 28. The Rabbit hole goes further with Invariant 2 and deletes, with DataKinds or GADTs. The deletes involve leaving the tree in an intermediate state where invariant 2 is broken. Not going there in this talk.
  • 30. So whats the problem here? What's the difference between the [a] / NonEmpty a case?
  • 31. All of the types could be injected into RBTree a much like NonEmpty a can be injected into [a]. But theres a conceivable use for [a], values exist. Other than implementing the core operations, users of the of the data structure should never encounter values that break the invariants.
  • 32. REFINING TYPES So far when I "refined" a type, I had to write up a completely new distinct type. Conversions between all these different types can be potentially inefficient. To "refine" [a], had to throw away the [] and build NonEmpty a from a again.
  • 33. We almost always use Type constructors to adulterate types (except for Const and Identity)
  • 34. So could we get more mileage from our types if we could qualify our types to restrict or refine them instead of adulterating them?
  • 35. type RedNode a = { t : RBTree a | ??? } type BlackNode a = { t : RBTree a | ??? } type RedBlack a = { t : RBTree a | ??? } type InsertState a = { t : RBTree a | ??? }
  • 39. Haha, goodness me no. You can see my very very very early attempt at using DataKinds and GADTs to do it here And a recent experiment with Liquid Types that doesn't quite work yet here.
  • 40. BINOMIAL TREES A primitive from which Binomial heaps are built: data BinomialTree a = BinomialTree a [a] Defined inductively as follows: Binomial tree of Rank 0 is a singleton node. A binomial tree of rank r + 1 is formed by linking two binomial trees of rank r, with one becoming a child of the other.
  • 41. MEASURES Liquid Haskell lets you define simple functions to use in constraints. They can't return functions though. {-@ measure binTreeRank :: BinomialTree a -> Int binTreeRank (BinomialTree x cs) = len cs @-}
  • 42. REFINED TYPES Or Liquid Types (Logically Qualified Data Types). Similar to Subset Types in Coq. {-@ type BinomialTreeN a N = {t : BinomialTree a | (binTreeRank t) = N} @-}
  • 43. INVARIANTS The inductive definition results in the following invariant: The list of children is ordered by decreasing rank, with each element 1 rank higher than the next...
  • 44. Encode invariants into the type: data BinomialTreeList a = Nil | Cons (BinomialTreeList a) (BinomialTree a) {-@ measure listlen :: BinomialTreeList a -> Int listlen (Nil) = 0 listlen (Cons xs x) = 1 + (listlen xs) @-} {-@ invariant {v : BinomialTreeList a | (listlen v) >= 0} @-} {-@ type BinomialTreeListN a N = {ts : BinomialTreeList a | (listlen ts) = N} @-} -- Invariant here {-@ data BinomialTreeList [listlen] a = Nil | Cons (ts :: BinomialTreeList a) (t :: BinomialTreeListN a {(listlen ts)}) @-}
  • 45. Let's store the rank in the structure and add an invariant for that also: data BinomialTree a = BinomialTree Int a (BinomialTreeList a) {-@ measure binTreeRank :: BinomialTree a -> Int binTreeRank (BinomialTree r x cs) = r @-} {-@ data BinomialTree a = BinomialTree (r :: Int) (x :: a) (cs :: BinomialTreeListN a {r}) @-}
  • 46. Can now provide guarantees on the outputs of functions that are statically checked: {-@ binlength :: t : BinomialTreeList a -> {x : Int | x = (listlen t)} @-} binlength :: BinomialTreeList a -> Int binlength Nil = 0 binlength (Cons ts _) = 1 + binlength ts {-@ rank :: v : BinomialTree a -> {x : Int | x = (binTreeRank v)} @-} rank :: BinomialTree a -> Int rank (BinomialTree r _ _) = r -- rank (BinomialTree _ _ cs) = binlength cs -- rank _ = 0
  • 47. Verify the inductive definition is preserved by our implementation of the core operations: -- | Singleton node defined to have rank 0 {-@ singletonTree :: a -> BinomialTreeN a {0} @-} singletonTree :: a -> BinomialTree a singletonTree x = BinomialTree 0 x Nil -- | Rank r + 1 tree is created by linking together two rank r trees. {-@ link :: (Ord a) => w : BinomialTree a -> z : BinomialTreeN a {(binTreeRank w)} -> BinomialTreeN a {1 + (binTreeRank w)} @-} link :: BinomialTree a -> BinomialTree a -> BinomialTree a link w@(BinomialTree rw x ws) z@(BinomialTree rz y zs) | x < y = BinomialTree (rw + 1) x (Cons ws z) | otherwise = BinomialTree (rz + 1) y (Cons zs w)
  • 49. PROS Don't have to manipulate proofs in parallel with program values. Some of the expressive capacity of Dependent Types
  • 50. LIMITATIONS 1 Only some of the expressive capacity of Dependent Types Can use any SMT solver backend apparently, but z3 is the only with a reliable enough reputation z3 is not free (Non-Commercial Research use only) Using an SMT solver is a little "black boxy", not sure I would ever want it in the compiler, don't know if that will ever take off Then again, I didn't think the IPod was going to be a big deal.
  • 51. LIMITATIONS 2 If refined types rule out specific patterns (e.g Red Black trees), fails exhaustivity checking in GHC since the function is effectively partial as far as GHC is concerned. A lot of the time, expressing properties/invariants/constraints is really just as challenging as doing so in the existing type system. So I don't think we have solved the Type complexity problem yet. At the moment its like a separate type system running in parallel, gets a little schizophrenic. Terrible error messages
  • 52. {-@ binlength :: t : BinomialTreeList a -> {x : Int | x = (listlen t)} @-} binlength :: BinomialTreeList a -> Int binlength Nil = 0 binlength (Cons ts _) = 2 + binlength ts src/Data/Binomial.hs:75:26-41: Error: Liquid Type Mismatch Inferred type VV : Int | (VV == (?c + ?a)) not a subtype of Required type VV : Int | (VV == (listlen ?b)) In Context ts : (BinomialTreeList a) | ((listlen ts) >= 0) ?b : (BinomialTreeList a) | ((listlen ?b) >= 0) ?a : Int | (?a == (listlen ts)) ?c : Int | (?c == (2 : int))
  • 53. REFERENCES AND FURTHER READING Z3 N. Vazou, E. L. Seidel, R. Jhala, D. Vytiniotis, and S. Peyton- Jones. Refinement types for Haskell Try Liquid Haskell - An Online Interactive Liquid Haskell Demo