A taste of Haskell


Paul Callaghan
(not that one)



Language
Wars ?



My aim today:
Haskell isn't hard
and it's worth a go



A bit of what
the books
don't tell you



What is
Haskell?



A load of
complex stuff?
(too much maths)



An exercise
in monasticism?



Job security
for academics?



An infinite supply
of PhD topics?



Haskell is really
a language for
playing with
data




Excellent tools for * defining new data types * building complex data * taking data apart * and doing big operations on it





Many ways to create types
Lists, Tuples/Records all built in
Adding other new data types is easy



data Port = Number Int | Name String data TreeA = NodeA (Int,Bool) [TreeA]





Easy to generalise types



data TreeB a = NodeB a [TreeB a] type TreeA = TreeB (Int,Bool)





Very powerful data types...



data TreeC c a = NodeC a (c (TreeC c a)) type TreeB a = TreeC [] a type TreeD a = TreeC (Day ->) a





So, a very rich and convenient
'(sub)language' for data types



* more precise about types you want * less work to add types you need





Constructing data



* syntactically clean language * few type annotations needed * powerful overloading support






t1 = NodeB "b" [ NodeB "a" [] , NodeB "c" [] , NodeB "d" [] ] t2 = NodeB "b" [ NodeB s [] | s <- ["a", "c", "d"] ]





Taking data apart
"Pattern matching" is a
mix of testing and extraction



leftChild (NodeB _ []) = Nothing leftChild (NodeB _ (NodeB x _:_)) = Just x





Nothing special about conditionals



if True yes no = yes if False yes no = no





Working with data


Easy to define common idioms
for processing data


Eg. 'mapping' same operation over a list


Or filtering values which pass a test




Higher order functions


... doing things with functions

map (\x -> x + 2) [1,2,3]


map is like a for-loop



Composing two functions



f . g = \x -> f (g x)




A fundamental operation
New functions from old



Programming with pipelines



foo = unwords . map reverse . words




"abc def ghi" to
"cba fed ihg"


Code is data


Haskell (almost) lets us treat
functions like any other kind of data


* very flexible
* very articulate



Notice the difference


Transformations on data,
rather than detailed list of steps


Declarative programming



Advanced type system


Few type annotations
Powerful type inference
No runtime checks at all
A useful safety net


Good balance!



Overloading


"Type classes" = name overloading
Superset of Java interfaces
Eg "show" on Ints and Strings
and [Int] and [[Int]] and [[[Int]]] and ...



The Real World


IO, State, Concurrency ...
Doesn't seem to fit nicely



The Real World has a type


type IO a = World -> (a, World)
Side effects change the world etc


If we compose these in right order,
things happen in the right order




Monads are not scary


Just a generalised wrapper
around things like World -> (a, World)


Allows imperative style
where needed



Does what it says...



main = do putStr "Type something" l <- getLine appendFile "f" $ "IN:" ++ show l





High-level programming with actions

mapM' [Monday .. Friday] $ \d -> do putStr $ "Day is: " ++ show d putStr $ show $ some_calc d





let acts = map putStr $ words "hi all" sequence acts




Easy to define new control structures
Trivial to implement callbacks too






A thought


How much of a program
needs state or IO?



Probably not much!


Many benefits
of clean separation


"Sin bin"...




Domain specific languages


Haskell's flexibility and syntax
strongly support embedded DSLs



This is a directly runnable parser



s = memo S $ iI np vp Ii np = memo NP $ term "n" <+> iI (term "d") (term "n") Ii <+> iI np pp Ii pp = memo PP $ iI (term "p") np Ii vp = memo VP $ iI (term "v") np Ii <+> iI vp pp Ii






student_info = do let cs = [ tr << map (td<<) [n, s_name n, t] | pn <- [1 .. maximum $ map fst projs] , S n d c <- sort all_people , current c == pn , let (P s _ _ t) = get_proj pn ] let header = tr << (map (th<<) ["uid", "name", "title"]) let doc = [ h1 << "Project allocation (2007-08)" , h2 << "Student names vs project titles" , table ! [border 1] << (header : cs) , h3 << anchor ! [href "..."] << "some page" ] writeFile "foo.html" $ show doc





... a database table join
formatting results in Html


echoes of LINQ?



Design principles


Think about the data and its operations
Use flexibility to create useful abstractions
Often good to invent DSLs to help


Typical: simple pieces with strong 'glue'



Testing etc


Hoare: No obvious defects,
vs obviously no defects


Code tends to be simpler,
and less chance for error


Some good testing tools exist



Performance issues


'Lazy' = slow?
Loss of 'control'?



Trust
your
compiler!



GHC is very advanced:
lots of fusion and inlining


Much better at it than you are


Good Analysis tools and
low-level options exist



A playground


Many experimental extensions
Lots of research activity
Strong community too



Still not there yet


Find the type error in the
following Haskell expression:



if null xs then tail xs else xs




Dependent types anyone?



Conclusion


Not much missing now
Quite a few advantages


Any one for a HUG?