first order haskell
DESCRIPTION
First Order Haskell. Neil Mitchell York University www.cs.york.ac.uk/~ndm. λ. First order vs Higher order. Higher order: functions are values Can be passed around Stored in data structure Harder for reasoning and analysis More syntactic forms Extra work for the analysis - PowerPoint PPT PresentationTRANSCRIPT
![Page 1: First Order Haskell](https://reader035.vdocuments.pub/reader035/viewer/2022072014/56812cb5550346895d91685a/html5/thumbnails/1.jpg)
First Order Haskell
Neil Mitchell
York University
www.cs.york.ac.uk/~ndmλ
![Page 2: First Order Haskell](https://reader035.vdocuments.pub/reader035/viewer/2022072014/56812cb5550346895d91685a/html5/thumbnails/2.jpg)
First order vs Higher order
Higher order: functions are values– Can be passed around– Stored in data structure
Harder for reasoning and analysis– More syntactic forms– Extra work for the analysis
Can we convert automatically?– Yes (that’s this talk!)
![Page 3: First Order Haskell](https://reader035.vdocuments.pub/reader035/viewer/2022072014/56812cb5550346895d91685a/html5/thumbnails/3.jpg)
Which are higher order?
[not x | x ← xs]let xs = x:xs in xs
putChar ‘a’
1
\x → not x
not . odd
not $ odd x
map not xs
foldl (+) 0 xs
a < b (+1)
const ‘N’
![Page 4: First Order Haskell](https://reader035.vdocuments.pub/reader035/viewer/2022072014/56812cb5550346895d91685a/html5/thumbnails/4.jpg)
Higher order features
Type classes are implemented as dictionaries– (==) :: Eq a a → a → Bool– (==) :: (a→a→Bool, a→a→Bool) → a → a → Bool
Monads are higher order– (>>=) :: Monad m m a → (a → m b) → m b
IO is higher order– newtype IO a = IO (World → (World, a))
![Page 5: First Order Haskell](https://reader035.vdocuments.pub/reader035/viewer/2022072014/56812cb5550346895d91685a/html5/thumbnails/5.jpg)
A map example
map f [] = []
map f (x:xs) = f x : map f xs
heads xs = map head xs
head is passed higher order map takes a higher order argument heads could be first order
![Page 6: First Order Haskell](https://reader035.vdocuments.pub/reader035/viewer/2022072014/56812cb5550346895d91685a/html5/thumbnails/6.jpg)
Reynold’s Style Defunctionalisation
data Func = Head
apply Head x = head x
map f [] = []
map f (x:xs) = apply f x : map f xs
heads xs = map Head xs
Move functions to data
John C. Reynolds, Definitional Interpreters for Higher-Order Programming Languages
![Page 7: First Order Haskell](https://reader035.vdocuments.pub/reader035/viewer/2022072014/56812cb5550346895d91685a/html5/thumbnails/7.jpg)
Reynold’s Style Defunctionalisation
Good– Complete, works on all programs– Easy to implement
Bad– No longer Hindley-Milner type correct– Makes the code more complex– Adds a level of indirection– Makes program analysis harder
![Page 8: First Order Haskell](https://reader035.vdocuments.pub/reader035/viewer/2022072014/56812cb5550346895d91685a/html5/thumbnails/8.jpg)
Specialisation
map_head [] = []
map_head (x:xs) = head x : map_head xs
heads xs = map_head xs
Move functions to code
![Page 9: First Order Haskell](https://reader035.vdocuments.pub/reader035/viewer/2022072014/56812cb5550346895d91685a/html5/thumbnails/9.jpg)
Specialisation
Find: map head xs– A call to a function (i.e. map)– With an argument which is higher order (i.e. head)
Generate: map_head xs = …– A new version of the function– With the higher order element frozen in
Replace: map_head xs– Use the specialised version
![Page 10: First Order Haskell](https://reader035.vdocuments.pub/reader035/viewer/2022072014/56812cb5550346895d91685a/html5/thumbnails/10.jpg)
Specialisation fails
(.) f g x = f (g x)
even = (.) not odd
check x = even x
Nothing available to specialise! Can be solved by a simple inline
check x = (.) not odd x
![Page 11: First Order Haskell](https://reader035.vdocuments.pub/reader035/viewer/2022072014/56812cb5550346895d91685a/html5/thumbnails/11.jpg)
An algorithm
1. Specialise as long as possible
2. Inline once
3. Goto 1
Stop when no higher order functions remain
![Page 12: First Order Haskell](https://reader035.vdocuments.pub/reader035/viewer/2022072014/56812cb5550346895d91685a/html5/thumbnails/12.jpg)
Algorithm fails
data Wrap a = Wrap (Wrap a) | Value a
f x = f (Wrap x)
check = f (Value head)
In practice, this is rare – requires a function to be stored in a recursive data structure and …
Detect, and revert to Reynold’s method
![Page 13: First Order Haskell](https://reader035.vdocuments.pub/reader035/viewer/2022072014/56812cb5550346895d91685a/html5/thumbnails/13.jpg)
Code Size
Specialisation approach reduces code volume– Average about 55% smaller code (20%-95% range)
Mark Jones, Dictionary-free Overloading by Partial Evaluation
0
500
1000
1500
2000
2500
3000
Nofib Programs (Imaginary)
Lin
es o
f C
od
e Higher order
First order
![Page 14: First Order Haskell](https://reader035.vdocuments.pub/reader035/viewer/2022072014/56812cb5550346895d91685a/html5/thumbnails/14.jpg)
Current uses
Performance optimiser– The first step, makes the remaining analysis simpler– Already increases the performance
Analysis tool– Catch, checking for pattern match safety– Keeps the analysis simpler
Implemented for Yhc (York Haskell Compiler)
![Page 15: First Order Haskell](https://reader035.vdocuments.pub/reader035/viewer/2022072014/56812cb5550346895d91685a/html5/thumbnails/15.jpg)
Conclusion
Higher order functions are good for programmers
Analysis and transformation are simpler in a first order language
Higher order functions can be removed Their removal can reduce code size