Learn to program in Haskell

A place for impromptu lectures or debates. Stir up controversy, just like the forum's namesake, Kaiser Leto III the Bold!
Post Reply
User avatar
Ari Rahikkala
Posts: 4326
Joined: Sun Jan 21, 2001 12:56 pm
Contact:

Learn to program in Haskell

Post by Ari Rahikkala »

OK, this one's going to be a bit experimental. This is an introductory programming class, intended for people who have never written a line of code in their life before. Having never done this before, I have no idea how difficult this is going to be, but the plan is to make it as easy as possible: If you want difficult stuff, you're welcome to make some for yourself :). If all goes well, you'll soon enough be looking at claims about how programming is difficult and wondering whoever could ever think that...

People who have programmed before are welcome to join in too, but it's going to be... different for them. I realise that the first lessons will seem incredibly simple to you, but I recommend you join in right away anyway, because it will help you to unlearn the things that you really do need to unlearn to understand the later ones.

Lessons will be posted irregularly, and they will have a format much like this one: An introductory text, and a bunch of exercises. I will wait until at least one person has posted the answers to the exercises (go ahead and post them in this thread) before moving on to the next lesson.

----

An expression is a mathematical construct. It evaluates to a value. I will be using "<>" as shorthand for "evaluates to" here. "--", which is Haskell syntax, stands for "the rest of the line is a description of what's going on here". "==" stands for "equals".

Code: Select all

3 + 5      <> 8   -- adding up two numbers evaluates to another number

4          <> 4  -- a number evaluates to itself

4 == 5     <> False -- asking if one thing is the same as another evaluates to a truth value, aka a Bool

3 + 5 == 8 <> True -- an expression is the same as its value
An expression can be given a name by binding it with "=" (note that this is not the same as "=="). An expression so bound can be used in other expressions as if it were written out in full, within parentheses.

Code: Select all

seven = 2 + 5 -- the name "seven" is now bound

14 / seven <> 14 / (2 + 5) 
           <> 2

A function is an expression that takes arguments (expressions), aka parameters. Functions are written in two parts: A list of formal parameters, and a function body. Formal parameters also occur inside a function body: When a function is applied to arguments, the formal parameters in the function body are bound to the respective given arguments (so, when evaluating by hand, you just replace the former with the latter). The list of formal parameters is thrown away as it becomes unnecessary.

"\", aka lambda (it's actually supposed to be t it's easier to type \), stands for "what comes next is the list of formal parameters", while "->" stands for "what comes next is the function body":

The syntax for applying a function to arguments is simple: Just write out the function (or its name), then its arguments. Once you install a Haskell implementation this will be all you need to do to use a function: We're only doing things the hard way in this first lesson.

Code: Select all

\x -> x + 5 -- this is a function that adds 5 to a given argument

(\x -> x + 5) 2 <> 2 + 5 -- a function can be used directly...  
                <> 7     

square = \x -> x * x -- ... or given a name by binding it with "="

square seven <> (\x -> x * x) 7 -- bound names can be given as arguments just like any other expression
             <> 7 * 7
             <> 49 

energy = \mass velocity -> 0.5 * mass * velocity * velocity -- a function can have several arguments

energy 5 2 <> 0.5 * 5 * 2 * 2   
           <>   10
The notation with lambdas bears some similarity to the traditional way functions are defined with mathematics. For instance, square could be written as square(x) = x * x.

When a function, given arguments, is evaluated to a value, it is said to return that value.

Function definitions can be written in shorthand by writing the list of formal parameters before the "=" and the function body after it, and leaving out the "\" and the "->":

Code: Select all

energy mass velocity = 0.5 * mass * velocity * velocity -- this is the same as the earlier definition
To be able to program meaningfully, you need conditionals. The one that we will handle in this lesson is the if-then-else expression. What's between "if" and "then" must be an expression that evaluates to Bool (a truth value) for an if-then-else to be valid. If it evaluates to True, the whole expression evaluates to what's between "then" and "else", otherwise it evaluates to what's after "else":

Code: Select all

max x y = if x > y then x else y


Exercises:

Evaluate these expressions by hand. No intermediate steps needed, just the final value (I will tell you if it's wrong and we can work it out together):

1. 5 + 6
2. (\x -> x + 6) 5

average x y = (x + y) / 2

3. average 2 4
4. average (max seven 10) 0
5. average 2 4 == 3

Also, define a function that takes one argument, and if that argument is less than 0, returns it negated, otherwise unchanged.

(some supplemental exercises: If that last exercise seems difficult to you, try to implement a couple of simpler functions at first. For instance, try implementing the three functions whose bodies will be the bits that you need to fit around the if-then-else expression: negative (check if its argument is smaller than 0), negate (negate its argument by putting a minus sign in front of it) and identity (return its argument unchanged). Actually, I'll just give that last function to you: It's \x -> x.)

Finally, go to Haskell.org and look around as you like.

In the next lesson, we will (among other things):
- install and configure a Haskell implementation so that you can have your computer evaluate expressions for you
- get started on learning what that cryptic heading of haskell.org means: We will be using types and higher-order functions
- recurse!
Last edited by Ari Rahikkala on Wed Jul 18, 2007 12:24 am, edited 4 times in total.
No-one should be without a parasol, Sirocco.

User avatar
Ari Rahikkala
Posts: 4326
Joined: Sun Jan 21, 2001 12:56 pm
Contact:

Post by Ari Rahikkala »

Oh, and a few general notes:

- I'm sure you all got the memo, but in case you didn't: There are stupid questions, but there are no stupid people asking questions, and even if you asked a stupid question I wouldn't tell you it was stupid anyway :)
- in fact, even if you don't have anything to ask, please provide crushing criticism... or, well, at least tell me you're with me if you are. That's the only way I will know how well *I* am doing :)
- I know I didn't follow any sort of procedure in starting this class without asking anyone. If anyone's got a problem with that they're welcome to take it up with me :p
No-one should be without a parasol, Sirocco.

User avatar
Jonas
Posts: 5334
Joined: Mon Feb 19, 2007 9:53 am

Post by Jonas »

Ari Rahikkala wrote:There are stupid questions, but there are no stupid people asking questions, and even if you asked a stupid question I wouldn't tell you it was stupid anyway :)
Are you sure about that?
From a distance I'm concerned about the rampant lawyerism manifesting itself in Shireroth currently. A simple Kaiserial slap on the wrist or censure by the community should suffice. - Jacobus Loki
Can't you see? I'm crazy! :tomcutterhamonfire :smashy

User avatar
Ari Rahikkala
Posts: 4326
Joined: Sun Jan 21, 2001 12:56 pm
Contact:

Post by Ari Rahikkala »

It's for motivation. Life will simply be a lot easier for all of us if you believe it :). Now get cracking! I've already clarified this lesson using advice from normal people, normal micronationalists like you who haven't got much experience of formal languages... and I truly, honestly *want* to see people understand it, so whatever you find difficult for you in here - go ahead and ask about it!
No-one should be without a parasol, Sirocco.

User avatar
Neike Taika-Tessaro
Posts: 247
Joined: Tue Jul 04, 2006 12:20 pm
Location: Altamont, Dark Arcadia | Germany
Contact:

Post by Neike Taika-Tessaro »

Heeheehee. Haskell rocks, in a sadomasochistic sort of way.

The exam I'm going to write at the end of August involves programming patterns, with Haskell-style pseudocode to illustrate them. As such, I'm all ears for this, as it might help me understand the inner workings of Haskell, which our prof' never stopped to explain, really. :-P
Neike Taika-Tessaro, Archon of Dark Arcadia
Image

User avatar
Ari Rahikkala
Posts: 4326
Joined: Sun Jan 21, 2001 12:56 pm
Contact:

Post by Ari Rahikkala »

Neike Taika-Tessaro wrote:Heeheehee. Haskell rocks, in a sadomasochistic sort of way.
As I said... to people who have done programming before, it will be... different. Didn't say it would be different in a good way :p. (and FWIW, it sure did look scary to me when I was first learning it not at all very long ago)
No-one should be without a parasol, Sirocco.

User avatar
Ari Rahikkala
Posts: 4326
Joined: Sun Jan 21, 2001 12:56 pm
Contact:

Post by Ari Rahikkala »

A few parting notes before I go to sleep... Dr-Spangle made a very good effort at solving the exercises on IRC, although he didn't quite grasp the function definition exercise yet, and expression #4 caused some problems to him. Therefore, here's a little help...

In expression #4, remember, you start by evaluating what's inside the parentheses. Figure out what "max seven 10" is first - and once you know that, just replace it with the value you got.

In the function definition... I already edited in a few hints to the first post, but here's a few more: You *are* going to need an if-then-else expression in here, and you're going to need to mention the formal parameter several times in the function body (i.e. if you start the function definition by "\y ->", then you can't avoid mentioning y several times in what follows).

I want to see some answers to the exercises in this thread when I wake up in the morning :nuclear !
No-one should be without a parasol, Sirocco.

User avatar
Ari Rahikkala
Posts: 4326
Joined: Sun Jan 21, 2001 12:56 pm
Contact:

Post by Ari Rahikkala »

Lesson 1.5 is posted now. If you had problems with evaluating these expressions, getting to play with GHC should help as it will evaluate them for you - you will never have to evaluate a Haskell expression by hand again :) !. Also, I'm going to give you guys a bit more time to stomach these lessons from now on since I know there's only so far that you can go before smoke starts coming out of your ears...
No-one should be without a parasol, Sirocco.

Kaiser Letifer III
Posts: 242
Joined: Fri May 25, 2007 2:05 pm

Post by Kaiser Letifer III »

1. 5 + 6 <> 11
2. (\x -> x + 6) 5 <> 11

3. Average 2 4 <> 3
4. average (max seven 10) 0 <> 5
5. average 2 4 == 3 <> TRUE

function x = (if x < 0 then x * -1 else x) --I find this way or declaration more familiar then the /x and -> way...

User avatar
Neike Taika-Tessaro
Posts: 247
Joined: Tue Jul 04, 2006 12:20 pm
Location: Altamont, Dark Arcadia | Germany
Contact:

Re: Learn to program in Haskell

Post by Neike Taika-Tessaro »

Ari Rahikkala wrote:Function definitions can be written in shorthand by writing the list of formal parameters before the "=" and the function body after it, and leaving out the "" and the "->":

Code: Select all

energy mass velocity = 0.5 * mass * velocity * velocity -- this is the same as the earlier definition
That's not just a function, though; that's a function that's been given a name. I realise this is obvious, but part of what I'm really enjoying about your lesson so far, is that it's very precise. :) (Which, in turn, is why I'm coming here now that I'm finally squat in the middle of learning about programming patterns, since we're using Haskell to model.)

1. 5 + 6 <> 11
2. (\x -> x + 6) 5 <> 11
3. average 2 4 <> 3
4. average (max seven 10) 0 <> 5 -- under the condition that 'max' and 'seven' are defined as in your code above; otherwise, I don't know what Haskell does when you try and call a non-existant function / value.
5. average 2 4 == 3 <> True
Also, define a function that takes one argument, and if that argument is less than 0, returns it negated, otherwise unchanged.
abs x = if x < 0 then 0-x else x -- I know, the 0 in the then-expression is obsolete, I've just never been a fan of unary operators where it can be avoided.

Let me know if I've done anything unelegantly (or downright wrong), please. :)
Neike Taika-Tessaro, Archon of Dark Arcadia
Image

User avatar
Neike Taika-Tessaro
Posts: 247
Joined: Tue Jul 04, 2006 12:20 pm
Location: Altamont, Dark Arcadia | Germany
Contact:

Post by Neike Taika-Tessaro »

For those of you who took one look at this and went cross-eyed:

If you have some time, I recommend going through all of this again. I think what's important is that you try to ditch everything you do know - most importantly, try to 'forget' what a function is, and just accept it as precisely what Ari says it is.

I've done pretty much the same thing, and I feel that's helped. :)
Neike Taika-Tessaro, Archon of Dark Arcadia
Image

User avatar
Ari Rahikkala
Posts: 4326
Joined: Sun Jan 21, 2001 12:56 pm
Contact:

Post by Ari Rahikkala »

Neike, your answers were all correct (and elegant).

Erik, your answers were all correct except for a slight bug in the function definition: Haskell can't parse "x * -1" - it doesn't know whether it should be parsed as "(x * -) 1" or as "x * (- 1)". To understand how to fix this (other than just using the latter notation), read on :).
abs x = if x < 0 then 0-x else x -- I know, the 0 in the then-expression is obsolete, I've just never been a fan of unary operators where it can be avoided.
The (-) operator actually occasionally behaves in surprising ways because it can mean either subtraction or negation depending on syntactic context. Fortunately the Prelude has functions that make the difference manifest, called subtract and negate :).

To see what I mean with "surprising", try and see what Haskell says about expressions like "map (-5) [1..10]" (as opposed to "map (+5) [1..10]") or "const -1" (as opposed to "const (-1)").
No-one should be without a parasol, Sirocco.

Post Reply

Return to “Leto III Hall”

Who is online

Users browsing this forum: No registered users and 1 guest