Chapter 1 of Hudak's "Haskell School of Expression" is "Problem Solving, Programming and Calculation".
It's an introductory chapter, which has just enough on computation to serve as an introduction to someone coming to Haskell as their first programming language (eeeek!) It's also got a lot of good stuff, so it's worth not skipping even if you are an experienced programmer, especially if you're not coming from a Functional Programming background.
I've read this a couple of times, and I've done some of the exercises in YAHT and later on in the book, so in this entry, I'm just going to whizz through this and give some sample answers to each of the exercises.
Hudak introduces a function "simple" which he hangs many of the concepts in this chapter, and indeed, the rest of the book.
simple x y z = x * (y + z)
The first oddity about Haskell syntax is that the function parameters are separated by spaces. This is actually for reasons deep in the way that Haskell works, with curried function calls, but it feels odd
nonetheless when starting with Haskell!
I have the Glasgow Haskell Compiler, which I installed on my ubuntu laptop by running
$ sudo apt-get install ghc
I open the Interactive prompt by running
and try the above definition. It doesn't work.
Prelude> simple x y z = x * (y + z)
<interactive>:1:13: parse error on input `='
So I create a file called 1.hs containing just that definition and load it into the interpreter. That works.
Prelude> :load 1
Compiling Main ( 1.hs, interpreted )
Ok, modules loaded: Main.
*Main> simple 1 2 3
Why? No idea.
UPDATE: pjd, over on #haskell (freenode) reminded me that I'd need to do
> let simple x y z = x * (y + z)
instead. You need to prefix definitions with "let" in ghci, because it works in an implicit "do" block.
Hudak now starts talking about proving properties of programs. Part of me thinks that this is ivory tower madness… Then again, until I started unit testing, I didn't see how much benefit that was, so let's give it a go.
Ex 1.1: Write out all of the steps in the calculation of the value of
simple ( simple 2 3 4) 5 6
Remember that: simple x y z = x * (y + z)
simple 2 3 4 = 2 * (3 + 4)
simple 2 3 4 = 2 * 7
simple 2 3 4 = 14
simple (simple 2 3 4) 5 6
simple (14) 5 6
simple 14 5 6 = 14 * (5 + 6)
simple 14 5 6 = 14 * 11
simple 14 5 6 = 154
Ex 1.2: Prove by calculation that
simple (a – b) a b => a^2 – b^2
simple (a – b) a b = (a – b) * (a + b)
Which I already remember from GCSE mathematics as expanding to a^2-b^2, but lets humour the exercise…
(a – b) * (a + b)
= (a^2 + ab – ba -b^2)
= (a^2 – b^2)
Section 1.2. Haskell types are incredibly powerful! And also rather odd. It seems odd that, for example the type signature of simple is:
simple :: Integer -> Integer -> Integer -> Integer
I'd think of it as (Integer, Integer, Integer) -> Integer, but again this seems to have to do with the way function calls are made in Haskell.
Another oddity is the obsession that people writing FP books have with writing in fonts that you can't type. He apologises about writing -> rather than the "nice" right arrow symbol.
Exercise 1.3: Identify the well-typed expressions in the following and give their types.
[(2,3),(4,5)] :: [(Int,Int)]
Now, I remember from somewhere (possibly YAHT?) that in the interactive shell, ":t" will allow you to check the type of an expression. As it happens, ghc has a slightly different answer:
*Main> :t [(2,3),(4,5)]
[(2,3),(4,5)] :: (Num a, Num b) => [(a, b)]
It's inferred that the numbers could be any type of number, not just integers. You can though set the list to be just take [(Int,Int)] like I'd suggested!
*Main> :t [(2,3),(4,5)] :: [(Int,Int)]
[(2,3),(4,5)] :: [(Int,Int)] :: [(Int, Int)]
['z',42] — I guess this will be ill typed as Haskell lists can't be heterogenous.
('z', -42) :: Num a => (Char, a)
on the basis of the Num a thing above. And, yes! That's correct.
simple 'a' 'b' 'c'
I guess this will be ill typed… and it is
(simple 1 2 3, simple) :: Num a => (a, a -> a -> a -> a)
No, but close! It's actually
*Main> :t (simple 1 2 3, simple)
(simple 1 2 3, simple) :: (Num a, Num a1) =>
(a, a1 -> a1 -> a1 -> a1)
Section 1.4. This is all rather nice, giving an example of breaking up a function, abstracting subdefinitions, and introducing "let" expresions, basically lexically scoped subroutines, very nice.
That's it for chapter 1! This is probably more useful for me than for anyone else, as by brain-dumping this here, I clarify my ideas on how this stuff really works. But comments are welcome!
UPDATE: By the way, comments about whether citing Hudak's examples is covered by "fair use" is welcome. I'm certainly very much recommending the book, and I believe that the citations are respectful and fair, but please do let me know!