SPA 2009 Day 1 – Real World Haskell

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:

  1. purity – execution and evaluation separate
  2. types – lots of checking
  3. 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

Published by Matt

I write software, and love learning how to do it even better.

Leave a comment

Your email address will not be published. Required fields are marked *