Info for a talk on Haskell I will be presenting
It doesn't really show you much, but if we must:
main = putStrLn "Hello, World!"
As with many languages, main is the main entry point from outside.
Simple but well-known recursive math algorithms like factorial are often thhought of as the "Hello World"s of functional languages. An implementation of factorial in Haskell:
fact 0 = 1 fact x = x * fact (x - 1)
Haskell employs something called pattern matching to handle incoming arguments and bind them to symbols (like x above).
The patterns are matched in order from the top. If the incoming value is 0, the function evaluates to 1. Anything else and the incoming value is bound to the symbol x to be used within the scope of that second definition.
Some FP and Haskell basics
- It's usually a compiled language and is typically compiled to binary (as opposed to a bytecode for a VM, although work is being done in this area).
- Haskell is garbage collected.
- Purity - Haskell is a pure functional language
- What does purity mean in this context?
- Purity refers to whether or not a programming language allows "destructive assignment". The idea of immutability is also sometimes called "referential transparency"
An example from procedural:
> $x = 10; > print "$x\n"; > $x++; # Referring to $x after this point, different value > print "$x\n";
This is not permitted in a pure language. In Haskell:
> x = 10
That's it, in this scope, x can not ever be anything but 10 for the remainder of this execution.
- Why do we care?
- Expressions never changing has interesting implications. You no longer care about _when_ something is referred to. If x = 10 and can never be changed, it no longer matters when different parts of your code make reference to it. The sequencing in time of things is irrelevent. You don't write code with that in mind. You only set up the relationship between expressions.
It seems counter-intuitive at first, coming from where we do. But it can also be liberating to not have to consider the sequence of events most of the time. It can make solving problems a simpler exercise.
- One effect of this is that traditional loops are generally not done in functional programming. You rely on recursion to represent the changing state of a loop control variable. As in this common example of calculating factorials above.
- All of this pure code is deterministic. Something set equal to something else is meaningful in the mathematics sense. It's true now and always. It's deterministic. You can rely on a given function called with certain arguments to always evaluate to the same result, period. No side-effects.
- In such an environment, the compiler is free to inline like mad. A large expensive computation in some function is guaranteed to only ever be performed once for some set of inputs. Put another way the language has built-in caching or "memoization". You get it for free without doing anything. It's the normal state of things in Haskell.
- What happens then, is that you explicitly design regions of your code to be impure. You deliberately make something stateful or sequential. You do this in a controlled manner. It's the normal state of things in procedural and object-oriented systems to make almost everything stateful regardless of whether it needs to be.
- Haskell is non-strict
- What is strictness?
- Strictness is non-lazy evaluation.
- Why do we care?
- Past, present and future
- The name "Haskell"
- Something brief about Curry, Church and the lambda calculus.
- Who was Haskell Curry?
- Haskell was named after Haskell Curry who was a logician from early in the last century.
- He is credited with development of some important topics in CS.
- Function currying (partial evaluation) is named after him.
- What is currying?
(+) :: Num a => a -> a -> a
(+ 5) :: Num a => a -> a
Now this (+ 5) is a complete function, you can call it with another number. You can pass it as a parameter anywhere that expects an expression of that type.
- Origin of Haskell
- Designed around 1990 to be a pure, non-strict functional language.
- For a long time Haskell didn't have any standarized way to interface with the "impure" real-world until some breakthrough research was done in the late 90s. It was at this time that things like type class Monad and friends became part of the base API. This has allowed Haskell to be more suited for practical development tasks.
- Many libraries available already with more all the time:
- HUnit unit testing framework, based on JUnit and friends
- QuickCheck automated test case generation
- regular expression library
- HSQL, simple library providing an interface to multiple databases. MySQL, PostgreSQL, ODBC, SQLite and Oracle are currently supported.
- HDBC, modeled loosely on Perl's DBI interface
- X11, Gtk2Hs, wxHaskell X GUI libraries, there are many more
- Web development from low-level CGI to more sophisticated web application frameworks like WASH and happs
- HaXml, HXT, XML parsing, manipulation and creation libraries.
- Many practical projects being worked on today
- A distributed source control management system written in Haskell. This is similar to other distributed SCMs like bzr, Mercurial and Git. Most Haskell projects are kept in darcs repositories but this is a general purpose piece of software suitable for projects of any kind.
- A rewrite of the XWindows window manager dwm in Haskell.
- As far as lines of code goes as a metric:
The original C source of dwm was around 4000 LOC
The three-person team working on Xmonad built all of dwm's functionality and more (like adding session management, Xinerama support, more) in less than 500 lines of Haskell source and over a couple of months.
- This project makes extensive use of QuickCheck unit testing. Fixes and features are said to be very quick to perform.
- XXX detail about Pugs and Audrey's account of how it went at first.
- It seems like everywhere I look people are raving about superhuman feats of programming achievement when they work in Haskell. And they seem to have a lot of fun doing it.