A Whirlwind Tour of Haskell
- First Steps
- Curry for Breakfast
- Lazy Evaluation
In my article Functional Programming: Why Should You Care?, I gave a high-level overview of some of the things that make functional programming interesting. This week I'm going to extend that with some more concrete examples from Haskell. This isn't intended as a detailed Haskell tutorial—there are a great many well-written ones available on haskell.org already.
If you have downloaded the Haskell distribution from haskell.org, then you will already have the Glasgow Haskell Compiler (GHC) installed. If you run the ghci command from the terminal then you will be in a Haskell environment with a read-evaluate-print-loop (REPL) interface. This reads a line of Haskell code, executes it, and prints the result. You can use this to get a simple feel for Haskell.
You can now run some trivial Haskell code:
$ ghci GHCi, version 7.0.4: http://www.haskell.org/ghc/ :? for help Loading package ghc-prim ... linking ... done. Loading package integer-gmp ... linking ... done. Loading package base ... linking ... done. Loading package ffi-1.0 ... linking ... done. Prelude> 1 + 3 4
You shouldn't need to explicitly state types for any Haskell values. In the above example, we wrote a trivial expression that performed integer addition. You can ask the interpreter to tell you the type of an expression with the :type directive:
Prelude> :type 1 1 :: Num a => a Prelude> :type 1 + 3 1 + 3 :: Num a => a
The part on the right of the :: is the type. This says that a is a type that is a Num, and that this expression reduces to a value of the same type. That's a bit confusing, but fortunately it becomes clearer when you have a slightly more complex example. Let's start by defining a simple function that increments a value and then ask its type:
Prelude> let inc x = x + 1 Prelude> :type inc inc :: Num a => a -> a
This is a function type, as you can tell by the fact that it has a -> in its name. Specifically a function that takes a value of some type a and returns a value of the same type. The type a must be a Num—some sort of numeric type. How does GHC know this? Because you use the function uses the + operator, which is defined only on numeric types. You can see this if you try adding two strings (lists of characters, in Haskell):
Prelude> "a" + "v"
:1:5: No instance for (Num [Char]) arising from a use of `+' Possible fix: add an instance declaration for (Num [Char]) In the expression: "a" + "v" In an equation for `it': it = "a" + "v"
This error says there is no way of converting from a [Char] (a list of characters) to an integer, and so there is no way of adding two [Char]s, and so this expression can't be evaluated.