This session was a marathon 6 hour tutorial introduction to Haskell on a sunny Sunday afternoon. I’d installed the GHC beforehand and tried out a couple of ‘hello world’ style tutorials, but other than that walked in with no experience of Haskell or any other functional programming.
Here are my notes:
Basic Syntax
make up new types with
{{lang:haskell}}
type Lat = Double
Backticks add syntactic sugar to re-arrange the normal order of “function arg arg”:
{{lang:haskell}}
div 5 6 == 5 `div` 6
indentation is important:
{{lang:haskell}}
latLngDistance lat1 lng1 lat2 lng2 =
sqrt((latD * latD) + (lngD * lngD))
where latD = latDistance lat1 lat2
lngD = lngDistance lng1 lng2
Lists
Strings are just lists (aka arrays) of characters, but rendered differently.
Use colons to construct lists:
{{lang:haskell}}
1 : 2 : 3 : [] == [1, 2, 3]
Colon adds to front of list, but is ‘right-associative’ so the right-most expression is evaluated first
{{lang:haskell}}
1 : (2 : (3 : [])) == [1, 2, 3]
Many operators are written in haskel themselves. ‘Prelude’ is a library full of these.
Functions on lists
{{lang:haskell}}
westmost [] = 0.0
westmost [lng] = lng
westmost (lng : lngs) = wester lng (westmost lngs)
Left-hand side is a pattern for parsing / matching and then splitting (for use) the input arguments. A more verbose way of doing the last one would be:
{{lang:haskell}}
westmost lngs = wester (head lngs) (westmost (tail lngs))
Guards can extend the patterns with conditions:
{{lang:haskell}}
wester lng1 lng2
| lng1 < lng2 = lng1
| otherwise = lng2
Defining Types
{{lang:haskell}}
type Lat = Double
type Lng = Double
type Name = String
data Location = Location Lat Lng Name
Second Location is the name of the constructor. Doesn’t have to match the type name.
With data types, you still have to use pattern matching to pull out the memebers:
{{lang:haskell}}
distance (Location lat1 lng2 _) (Location lat2 lng2 _)
sqrt((latD * latD) + (lngD * lngD))
where latD = latDistance lat1 lat2
lngD = lngDistance lng1 lng2
Underscore is just used to say ‘blah’ – don’t care about this matched element.
Point-free Style
{{lang:haskell}}
let double xs = map (*2) xs
let double = map (*2)
double [1..5]
This is a name for the practice of leaving the last argument out to build a special function that’s more generic.
{{lang:haskell}}
prepend s = (s ++)
append s = (++ s)
saveLocs =
writeFile "output.blah" . prepend prefix . append suffix
or
{{lang:haskell}}
saveLocs arg =
writeFile "output.blah" (prepend prefix (append suffix arg))
You can even do this (with arity 2 functions)
{{lang:haskell}}
prepend = (++)
append = flip prepend
Dot Function
{{lang:haskell}}
(.) f g a = f (g a)
Lazy
Haskell is lazy. You can think of each function as pulling just what it needs from the next function. E.g. we can create a list of all integeers:
{{lang:haskell}}
allInts = [1..]
So you can do stupid stuff:
{{lang:haskell}}
reverse [1..]
This will just hang forever. Or
{{lang:haskell}}
infiniteListOfOnes = 1 : infiniteListOfOnes
Parametric Polymorphism
Argh.
Classes
A class is similar to an interface or Mixin, but it NOT a type.
It basically defines a protocol that will be implemented by a type.
{{lang:haskell}}
class Collection c where
cLength :: c a -> Int
cMap :: (a -> b) -> c a -> c b
instance then defines the implementation for a specific type
{{lang:haskell}}
instance collection [] where
cLength = length
cMap = map
instance collection Tree where
cLength = <tree length function>
cMap = <tree map function>
Like generics in Java.
IO Actions
IO is impure, so when you want IO done, what you actually do is define an action, which will be lazy evaluated (i.e. executed) as necessary.
There is a syntax for this where you use chevrons to create actions with several steps. Or you can use the nicer ‘do’ syntax.
Type Signatures
It’s common to use type signatures even though you don’t have to. It helps you think about the goal for a new function before you write it, and it gives you machine-run safety checks
for free. Common to use them, at least for top-level function.
Uses in the Real World
Ben is using Haskell at Barcap where they have an embedded DSL which quants use to describe products. Haskell then compiles those descriptions, giving them a bunch of checks for the validity of the description.
Seems like Haskell is a good fit where you want to build DLSs with lots of type safety.
Why is it useful?
Key ideas that make Haskell special:
- purity – execution and evaluation separate
- types – lots of checking
- laziness
Community
Hoodlums – A user groups for people into Haskell. Formed at SPA last year. Once a month in London.
http://groups.bangstrom.com/hoodlums