Kids Coding

Complete series

  1. Kids Coding, Part 1
  2. Kids Coding, Part 2
  3. Kids Coding, Part 3
  4. Kids Coding Interlude: the function game
  5. Kids Coding, Part 4

Kids Coding, Part 1

Kids Coding, Part 1

I’ve been wanting to give my eldest child (Eliezer, now 10) a chance to learn to code for about a year now, with little success. My second child (Gavriella, now 8) is also ready to start learning some coding. “Ready” to me means “they have a decent enough grasp of written English.” (Yakov, my 6 year old, also wants in, but unfortunately is going to have to wait a bit.)

I know how I learned to code: sitting at a DOS prompt since the age of 2 and reading a massive “Teach Yourself QBasic in 21 Days” book. For various reasons, this doesn’t seem to apply to the next generation. I’ve looked into other modern approaches, including the graphical programming environments. My kids enjoyed some of this, but this week told me that “it’s fun, but we’re not learning anything.”

Previously, I tried teaching Eliezer some Haskell by writing up lessons for him. Whether because of my writing or his interest, it didn’t work at the time. I decided to not go down this path again, and an hour ago sat down with Eliezer and Gavriella for their first lesson. I’m winging this completely, but here’s the approach I’m taking:

This is the first of these summary blog posts. Caveats:

I considered making these private notes for myself instead, but thought some others may be interested, so I’m posting publicly.

Without further ado!

Python portion

This was the point where Eliezer commented that it looked a lot like the Haskell he’d seen. I’m not sure what it was, but somehow it clicked with him that whatever scared him off of Haskell previously wasn’t a real issue. We decided together to switch over to learning Haskell instead, which I’m quite happy about (more because I know the language better than anything else).

Haskell portion

Types

Today’s excercise

Note: Somewhere above, I briefly showed them that you could use do notation and put multiple print calls on different lines. No confusion from this at all. Relevant to the exercise:

I started them off with:

main = do
  | -- prompt started here

They both got the answer, one of them with a bit of help:

main = do
  print "2+3+4"
  print (2+3+4)

Things to note:

To figure out

Next lesson

I don’t want to plan out what to cover next time too intricately, because I want to experiment with them and bounce things around. I’m thinking about showing them how to create their own functions, maybe with lambda syntax, not sure.

Kids Coding, Part 2

I didn’t expect to be writing the second blog post only 12 hours after the first. But when the kids came downstairs this morning, they were unbelievably excited to do more coding. So here we are!

Eliezer and I discussed using more visual tooling (like Code World or Jupiter) for doing the learning, and I showed him what it looked like. It seems he’s got quite a bit of his father’s preferences, and wanted to stick to plain text for now. We’ll probably circle back to that kind of stuff after they get the basics. It will also give me a chance to get more comfortable with those offerings. (Thanks all for the recommendations on Reddit.)

One final note. I’m extremely happy that we went with Haskell after today’s lessons. Concepts like variable replacement which are natural in Haskell were great teaching tools. I obviously don’t have enough data to prove this yet, but I’m more strongly believing the long-held theory that Haskell is easier for brand new programmers than those familiar with imperative programming.

Coding environment

I moved us over to VSCode, with only syntax highlighting set up. Previously, I’d used my emacs setup with intero, and the red squiggles let them know they’d messed up too early. I used the docked terminal at the bottom, taught them to save, and showed them to press “up enter” in the terminal to rerun stack runghc foo.hs. Perhaps not the ideal setup, but definitely good enough.

Variables

Functions

Bonus

Gavriella kept playing with the code (wow, she’s focused on this). She decided she wanted to do division. That was more complicated, but she persevered. I taught her about div being a function that takes 2 arguments. She didn’t know anything about remainders, and was confused that div 15 2 worked at all. I taught her about divMod, and she did great.

Kids Coding, Part 3

Eliezer asked me a few questions about programming yesterday, and I ended up demonstrating a little bit about pattern matching. He then had a lot of fun showing a friend of his how programming works. I may end up giving some lessons to some of my kids’ friends in the next few weeks, which should be interesting.

Kids IDE

I’ve started using a minimalistic “kids IDE” I threw together for teaching the kids. It’s helped us not worry about details like filepaths, saving, and running in a terminal. It’s not a great tool, but good enough. I’ve included links to better tools in the README, though this fits my needs for the moment.

https://github.com/snoyberg/kids-haskell-ide#readme

I’ve set up AppVeyor to upload Windows executables to S3:

https://s3.amazonaws.com/www.snoyman.com/kids-ide/bin/kids-ide.exe

You’ll also need to install Stack.

Pattern matching strings

This morning, Eliezer and Gavriella both had their next “official” lesson. I started over with that pattern matching demonstration. First, I showed them this example:

main = do
  sayNickname "Eliezer"
  sayNickname "Gavriella"
  sayNickname "Yakov"
  sayNickname "Lavi"

sayNickname realname =
  putStrLn (nickname realname)

nickname "Eliezer" = "Elie Belly"
nickname "Gavriella" = "Galla Galla"
nickname "Lavi" = "Fat baby"
nickname "Yakov" = "Koko"

They got the basic idea of this. (And I ended up introducing putStrLn around here as well, which they were fine with.) However, as I had them typing out some of this on their own, they ended up with a lot of trouble around capitalization, which was a good introduction to Haskell’s rules around that. We’ll see how in a bit.

Pattern matching ints

After establishing that we could pattern match on strings, I switched the code to this:

main = do
  sayNickname 1
  sayNickname 2
  sayNickname 3
  sayNickname 4

sayNickname realname =
  putStrLn (nickname realname)

nickname 1 = "Elie Belly"
nickname "Gavriella" = "Galla Galla"
nickname "Lavi" = "Fat baby"
nickname "Yakov" = "Koko"

And gave them the challenge to rewrite nickname so that the code worked, which wasn’t too much of a problem. The misordering of Lavi and Yakov between main and nickname did cause some confusion, and then helped them understand better how pattern matching works. (I didn’t intentionally put that in, it somehow slipped in while the kids were working on rewriting things.)

Type signatures

I asked them what the type of nickname was, and they said function (yay!). And then explained to them that you can tell Haskell explicitly what a thing’s type is, and typed this in:

nickname :: ? -> ?

The funny syntax didn’t give them too much trouble, and then we got to fill in the question marks. I asked them what the output of the function was, pointing at the string. I was surprised: they said the type was “nickname” or “name.” They accepted that it was a string, but they didn’t like that. (New theory: humans’ brains are naturally strongly typed.)

I then asked what the input was, and they said “number.” I hadn’t taught them about Int yet, and didn’t know about integers from math, so I told them that integer is a kind of number, and that in Haskell we call it Int. Filling in the type signature was fine.

I pointed out that some things (like Int and String) were upper case, and some were lower case. I pointed out that concrete things that “actually exist” (maybe not the best terminology) are capitalized. We know what an Int is, for example. Variables are things we don’t know yet, and those are lowercase. And finally, you can put whatever you want inside a string, but it has to match exactly. That seemed to click fairly well for them.

Enums

I pointed out that referring to the kids as numbers isn’t good. (He responded that I actually do call them 1, 2, 4, and 8 sometimes…) Anyway, I said that a better type for the nickname function would be to take a Child as input. He said “can we say Child = Int,” which was a great insight. I showed up that, yes, we can do type Child = Int, but that there’s a better way.

I introduced the idea that data defines a new datatype, and then showed them:

data Child
  = Eliezer
  | Gavriella
  | Yakov
  | Lavi

Gavriella asked “what are those lines?” and I explained they mean “or.” Therefore, a child is Eliezer, or Gavriella, or Yakov, or Lavi. They got this.

Exercise: fix the following program, uncommenting the lines in main.

main = do
  sayNickname Eliezer
  --sayNickname Gavriella
  --sayNickname Yakov
  --sayNickname Lavi

sayNickname realname =
  putStrLn (nickname realname)

data Child
  = Eliezer
  | Gavriella
  | Yakov
  | Lavi

nickname :: Child -> String
nickname Eliezer = "Elie Belly"
--nickname 2 = "Galla Galla"
--nickname 3 = "Fat baby"
--nickname 4 = "Koko"

Some caveats where they got stuck:

I started to try and define data Person = Kid Child | Adult Parent, but realized quickly it was too complicated for now and aborted.

Recursion

I did not teach this well, the children did not get the concepts correctly. However, they did understand the code as I wrote it.

main = print total

total = addUp 10

addUp 10 = 10 + addUp 9
addUp 9 = 9 + addUp 8
addUp 8 = 8 + addUp 7
addUp 7 = 7 + addUp 6
addUp 6 = 6 + addUp 5
addUp 5 = 5 + addUp 4
addUp 4 = 4 + addUp 3
addUp 3 = 3 + addUp 2
addUp 2 = 2 + addUp 1
addUp 1 = 1 + addUp 0
addUp 0 = 0

They really hated how repetitive typing that out was, which was exactly the goal. It was easy to convince them that this was stupid. I then changed total to addUp 11 and it broke. They understood why, and so we started working on something better.

main = print total

total = addUp 10

addUp 0 = 0
addUp x = x + addUp (x - 1)

I stepped through the executable of this, complete with pattern matching. Doing this a few times in the future is probably a good idea.

Eliezer asked what happens if we remove the addUp 0 = 0 case. We discussed it, he said it wouldn’t work, and said it would “keep going.” I told him it was called an infinite loop, and we got a stack overflow. Good insight.

Gavriella asked how long it took me to learn this stuff. I told her 12 years; after all, I only started learning Haskell in my twenties. It made them feel pretty good that they were learning this stuff earlier than I did.

I gave them an exercise to implement multTo instead of addUp. They didn’t understand this, or recursion, and I had to help them through the whole thing. Mea culpa completely.

Gavriella asked for another exercise:

main = do
  sayAge Eliezer
  sayAge Gavriella
  sayAge Yakov
  sayAge Lavi

data Child = ...

sayAge child = print (age child)

age ? = ?

She typed something like:

age ? = ?
Eliezer=10

I showed her that she needed:

age Eliezer = 10

And then she got the rest just fine, though with a few capitalization mistakes.

Kids Coding Interlude: the function game

Since the kids have been back at school and we’ve been busy with work and some home renovations, I unfortunately haven’t had a chance to continue much with the kids coding training. However, when discussing the general topic of education at Functional Conf, the topic of “the function game” came up, and I wanted to share what we did. I found this a great—and perhaps vital—pre-training for Haskell.

The function game is simple: I pretend to be a function, let the kids give me input, and I give them output. They need to try to figure out what the function is. Here’s an example conversation:

Me: When you give me 1, I give you 2. When you give me 2, I give you 3.
Them: What if I give you 5?
Me: 6
Them: 8
Me: 9
Them: You’re just adding 1!

With each kid, I’ve always started off with addition. I’ll later get into identity, but that one is (perhaps surprisingly) more confusing for them. Multiplication by 2 is a good follow-up to addition. Then, when they get comfortable with discovering a few of these, I’ll throw in:

We’ll typically play this game at the dinner table. At some point I’ll also actually define a function for them, after they’ve already experienced some success at guessing what I’m doing:

It always gives the same output for the same input

The next curveball I introduce is different types:

Me: When you give me “apple”, I give you 5
Them: What?
Me: Functions don’t just work on numbers
Them: OK…
Me: When you give me “book”, I give you 4
Them: It’s the number of letters!

After that, each time I tell them I have a new function, they’ll ask me the type of the input. As a Haskeller father, I couldn’t be more proud :).

I’ll also teach them about functions of multiple inputs:

Me: When you give me 2 and 3, I give you 5
Them: What?
Me: Functions can take more than 1 input.

And after a few more examples, they figure out that I’m just doing addition.

I think I tried demonstrating partial function application by saying “when you give me 2, I give you a new function you can play with.” But I don’t remember if I actually did this, or if I just planned it. And since I’m sitting in a hotel lobby waiting for a cab, I can’t test out the theory on them right now.

Anyway, I hope this proves useful for others trying to teach their kids (or maybe non-kids!) either math or functional programming. If you try it out, please let me know how it goes.

Kids Coding, Part 4

Previous lessons have all been focused on teaching our ten and eight year olds some coding, since our six year old (Yakov) is still working on reading and writing in English. However, Yakov’s been home sick all week, and he asked me today to teach him some programming. So I came up with a simplified version focused solely on the GHCi prompt.

I started off with:

> x = 32
> x + x

And then I asked him what he thought the answer would be. He quickly came back with 64. Then I typed in:

> y = 5
> x + y

And he got 37 pretty quickly. We played around with a few more bits of simple arithmetic (he hasn’t really mastered multiplication yet). I introduced defining variables in terms of other variables:

> x = 2 * 3
> y = x * 2
> y + 3

This took him a bit longer, but entirely due to the multiplication! This showed me a few things:

  1. Reassigning variables was not confusing for him in the least
  2. Variable replacement was similarly trivial

Finally, I decided to push things just a bit further and introduce functions:

> f x = x + 3
> f 7

This confused him at first, but once I explained that this was applying the function f to the number 7, he got it, and said “oh, it’s the +3 function.” (Remember from last time that he’s been playing the function game for a while.) Next I hit:

> x = f 0
> f x

This was easy: it’s 6! Finally I gave him two more challenging ones:

> f (f 0)
> f (f (f 10))

I fully expected confusion about parentheses. I was shocked: he wasn’t bothered by them at all. He immediately got both answers, and was very proud of himself.

Total time: less than 10 minutes, probably closer to 5. Which is good, because he’s got a short attention span and wanted to play some Nintendo with me too. Overall, I was very happy with how many concepts he was able to absorb.

(Thanks to my ~/.ghc/ghci_history file for reminding me what we covered today.)