Haskell for Kids: Week 5

Functions and Variables!

Welcome to the week 5 summary of my Haskell class for kids. You can go back and read the previous weeks summaries, if you like:

Our theme this week will be functions and variables.

Section 1: How to Draw an Awesome Elephant

We started with a simple example. We already know how to draw a star:

star = polygon [ ( -75, -100), ( 0, 87), ( 75, -100), (-100, 25), ( 100, 25), ( -75, -100) ]

and Sophia has figured out how to draw an elephant (this is one of her early versions, actually, but I picked it because it’s shorter; you don’t need to understand it):

elephant = pictures [ rotate (-20) (scale 3 2 (translate 30 40 (circleSolid 25))), translate 150 (-20) (rectangleSolid 40 80), translate (-10) 40 (scale 1.5 1 (circleSolid 80)), translate 50 (-50)(rectangleSolid 40 70), translate (-60) (-50) (rectangleSolid 40 70), translate (-140) 50 (rotate 100 (rectangleSolid 10 40)) ]

But now we want to draw a really awesome star. Being “awesome”, of course, means being twice as large, and the color chartreuse.

awesomeStar = scale 2 2 (color chartreuse star)

awesomeElephant = scale 2 2 (color chartreuse elephant)

and

But, by now, you can probably guess that I can draw an awesome version of any picture. There are awesome spaceships, awesome shoes, awesome bicycles… give me any picture at all, and I can tell you how to draw an awesome one: you draw it twice as big, and make it chartreuse. It will get tiresome to keep repeating ourselves, but luckily, Haskell lets us say this just once:

awesome x = scale 2 2 (color chartreuse x)

Now we don’t need to define a bunch of variables like awesomeStar and awesomeElephant. Instead, we can just write awesome star, with a space in between the two!

We’ve seen things like this before: awesome is called a function, and the thing that we’re making awesome is called its argument. But up until now, we’d only used functions that other people gave us… like rotate and translate in the Gloss library. Now, we know how to write definitions for our own functions.

To sum up, we can write a function because:

Given any thing, we know how to make it awesome. It follows a formula: scale 2 2 (color chartreuse ____________) where you just fill in the blank.

If both of those are true, you can write a function definition. It looks like like the variable definitions we’ve written before, except that it has parameters. A parameter is any word that comes before the equal sign (=), except for the first one. In the function we wrote a minute ago, we called the parameter x. Parameters are just placeholders, so when you use the function, you’ll give it an argument, that argument gets stuck in where ever that variable name pops up.

We also talked about what it means to be cute, and came up with the following:

cute x = scale 0.5 0.5 (color purple x)

Let’s check our assumptions: given any shape you choose to define, we can draw a cute one. It follows a definite formula (make it half the size, and color it purple). And so we wrote a definition where the function is called cute, and the parameter is called x. If you wanted to draw a cute elephant, you could define picture like this: picture = cute elephant. There, the function is cute and the argument is elephant, so to figure out what that means you just replace x with elephant every time it shows up in the function definition for cute!

Section 2: In which elephants can move their tails…

Let’s look at another function. We know how to draw an elephant… but there’s one problem. No matter where we draw an elephant, its tail is always sticking out at exactly the same angle. Suppose we want to be able to draw an elephant with its tail sticking in whatever direction we like.

It turns out that almost all of drawing an elephant will remain the same, but there’s one rotate where we’ll want to change the angle. So once again, we have:

For any angle, we can draw an elephant with its tail at that angle. How we draw an elephant follows the same formula each time, except for a different number in that one place.

Sounds like a job for a function!

elephant angle = pictures [ rotate (-20) (scale 3 2 (translate 30 40 (circleSolid 25))), translate 150 (-20) (rectangleSolid 40 80), translate (-10) 40 (scale 1.5 1 (circleSolid 80)), translate 50 (-50)(rectangleSolid 40 70), translate (-60) (-50) (rectangleSolid 40 70), translate (-125) 50 (rotate angle (translate 0 20 (rectangleSolid 10 40))) ]

See how that worked? Most of the elephant stayed the same, but the rotate in the last line uses the parameter, angle. So whatever number we give it decides with way the tail points. It could be straight up…

picture = elephant 0

or it could be mostly down…

picture = elephant 160

So once again, we’re able to use functions: this time to say how to draw an elephant, but leave until later the question of which direction its tail should be pointing.

Section 3: Lists, Lists Everywhere

The interesting thing about functions was that they have parameters, which are special variables that can have different values depending on how you use the function. There’s another way that something similar can happen, and it’s in lists. So we’ll finish off by looking at some more kinds of lists.

The lists we’ve used so far have all looked something like this:

[ 1, 2, 3, 4, 5 ]

In other words, a list has always had an opening bracket, then some elements (that is, things in the list) separated by commas, and finally a closing bracket. The things in the list haven’t been numbers… we’ve worked with lists of pictures, and lists of points! You can have lists of whatever you want, but the form is the same: you still have the brackets and the commas. We can call these “simple lists”, because, they are pretty easy to use.

A second kind of list that will come in handy, that we haven’t used before, is a range. That looks like this:

[ 1 .. 10 ]

It always has an opening bracket, a first element, two dots in a row, and then a final element, and a closing bracket. This kind of list counts for you. The things inside (for now, at least) always have to be numbers so that you can count… and the computer will fill in the middle of the list for you. In this case, the list we defined is the same as [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]. The range is just a shorthand.

There’s one more simple trick we can play, too: we can give the first two elements, and the computer will continue the pattern:

[ 2, 4 .. 10 ]

This look almost like a range, except that we’ve given the first two elements, instead of the just the first one. The computer will notice that we skipped forward by two, and will keep doing that, so that list is the same as [2, 4, 6, 8, 10]!

Finally, we get to the most interesting kind of list of all: called a list comprehension. Here’s an example:

[ x + 7 | x <- [1 .. 5] ]

This has quite a few parts, so let’s go through them carefully:

It starts with an opening bracket, just like all lists.

Next is an expression. Notice that the expression has a variable x that we haven’t mentioned yet. That’s okay, it’s coming later.

In the middle, there’s a vertical bar (shift + backslash). That separates the expression from the next part.

Now we have a sort of definition of x, except we say that x is any thing from another list! We do that with a backwards arrow, which is typed as a less-than sign, followed by a dash.

Finally, there’s a closing bracket.

What this means is: give me a list of all values of (x+7), where x is any of the numbers in that list. So this is equivalent to [1+7, 2+7, 3+7, 4+7, 5+7]… and of course that is the same as [8, 9, 10, 11, 12].

This last kind of list is very, very interesting; but maybe right now it just looks very complicated and you can’t see why. To see how it’s interesting, we’ll start writing some lists of pictures, instead of just numbers.

Section 4: Combining List Comprehensions and Pictures

The last thing we did this week is combine pictures and list comprehensions to make some interesting pictures. I’ll give you a bunch of examples, but not the pictures they draw. Your task is to first try to guess what the picture will look like, and then try them out using the gloss programming web site and check your guesses.

I’d very strongly encourage you to take this seriously… use graph paper, work it out, and do your best to figure out what is going to be drawn before you run the program and check.

First example:

picture = pictures [ circle x | x <- [ 10, 20 .. 100 ] ]

Second example:

picture = pictures [ translate x 0 (circle 20) | x <- [ 0, 10 .. 100 ] ]

Third example

picture = pictures [ translate x 0 (circle x) | x <- [ 10, 20 .. 100 ] ]

Fourth example:

picture = pictures [ rotate x (rectangleWire 300 300) | x <- [ 0, 10 .. 90 ] ]

Fifth example:

picture = pictures [ translate x 0 (rotate x (rectangleWire 300 300)) | x <- [ -45, -35 .. 45 ] ]

We can also put several different variables on the right side of the vertical bar, separated by commas. In that case, we’ll get something in the list for each possible combination of those variables! We can use that, too…

Sixth example:

picture = pictures [ translate x y (circle 10) | x <- [ -200, -100 .. 200 ], y <- [ -200, -100 .. 200 ] ]

Seventh example:

picture = pictures [ rotate angle (translate x 0 (circle 10)) | x <- [50, 100 .. 200 ], angle <- [ 0, 45 .. 360 ] ]

Eighth example:

picture = pictures [ rotate angle (translate (5*x) 0 (circle x)) | x <- [10, 20 .. 40 ], angle <- [ 0, 45 .. 360 ] ]

As you can see, you can use list comprehensions to make lots of really cool pictures where it would be really tedious to write out each shape the way we’ve been doing before.

Your Assignment

Your assignment this week is to pick a picture with a lot of repetition that you can draw with list comprehensions, and build it. If you are in the United States and don’t have another idea, a really good one is the American flag!

Hints:

There’s a program to draw a star at the beginning of this summary. You can copy the star part from that if you like.

You’ll probably have to draw the stars in two groups: first, there’s a 5-row, 6-column bigger grid, and then there’s a 4-row, 5-column smaller grid inside of that.

You don’t have to draw a flag, though! Especially if you’re not in the United States, your flag probably doesn’t repeat as much as ours, so you’ll want to pick something different. Just pick something you can draw by using list comprehensions to make lists of pictures.

Have fun!

A Reference

One last thing… I’ve put together a reference card about the recent things we’ve done: lines, polygons, and types of lists. This might be a good thing to keep around. Click below to grab a copy.