Skip to content
August 20, 2011 / cdsmith

Animations Added to Web-Based Haskell/Gloss

The Feature

I’ve added animations to the web-based Gloss/Haskell environment at http://dac4.designacourse.com:8000/anim.  You should export a symbol

animation :: Float -> Picture

and you’ll see it in modern web browsers.  By “modern” we mean:

  • Firefox 6.0 or higher (yes, the one released just a couple days ago)
  • Chrome, Safari, or Opera, any recent version
  • The iOS browser should work (untested).
  • Internet Explorer and the built-in Android browser are known not to work.  On both operating systems, Firefox 6 is available and does work.

The feature we need is called “server sent events”, an HTML 5 extension that makes “comet” style web applications work without a whole tool shed of browser-specific kludges.  So, if you are curious about another browser, see if it implements server-sent events.  Or just try it.

Edit: As of Sunday, you can now do “simulations” as well.  The URL for simulations is http://dac4.designacourse.com:8000/sim.  These are a little more involved.  You need to define three symbols sharing a common data type of your choosing:

initial :: StdGen -> a
step :: ViewPort -> Float -> a -> a
draw :: a -> Picture

Here, initial returns the starting value of your chosen data type.  (Its parameter is a pseudo-random number generator, in case you want random numbers.)  The step function is responsible for “advancing” the simulation by some amount of time.  Finally, the draw function is reponsible for converting the current simulation to a picture to draw on the screen.  The difference between simulations and animations is that animations calculate the picture from scratch each time: you give it a time since the start, and get back a picture.  Simulations, on the other hand, play out incrementally: each new state depends only on the most recent state and the amount of time that’s passed since then.  You can always turn an animation into a simulation by defining initial = 0 and step = const (+) where the type “a” is Float.  But not all simulations can be efficiently written as animations.

Under the Hood

The previous version of the application (which still works just fine) displayed only static pictures, and did so by loading some JSON directly into the document and then having JavaScript draw it on a canvas.  This new animation mode is a little different.  The steps are:

  1. You submit your function.
  2. The server compiles your code (using SafeHaskell, of course), and stores your function along with the start time in a lookup table.
  3. The animation page loads, and has a key to that lookup table.
  4. The animation page connects back to the server using the JavaScript EventSource object (that’s the server-sent events feature).
  5. The server then streams newly updated pictures as JSON along that connection.

Incidentally, if you’re thinking of implementing a “comet”-style web application with Snap, you might be interested in the code at https://github.com/cdsmith/gloss-web/blob/master/src/EventStream.hs which implements the server side of the event stream format.  It’s a generic module that you can transplant into your own code.  In the future, I’ll look at the best way to get it packaged either as part of a snap package or as a stand-alone library.  As short as it is, though, I hope to avoid adding that dependency weight.

Anyway, that’s animations for you.  Have fun!

Examples

The following program draws the solar system, representing the distances of all the planets from the sun, their orbital periods, their relative sizes.  The one thing that’s not accurate is the relationship between the sizes of the planets and their distance from the sun… something had to give, since a completely to-scale representation of the solar system would just look empty!  Also, I didn’t bother representing the eccentricities of orbits.

import Graphics.Gloss

animation t = pictures [
    color black (rectangleSolid 500 500),
    sun,
    rotate (60 * t /   0.24) (translate   4 0 mercury),
    rotate (60 * t /   0.62) (translate   7 0 venus),
    rotate (60 * t /   1.00) (translate   9 0 earth),
    rotate (60 * t /   1.88) (translate  14 0 mars),
    rotate (60 * t /  11.86) (translate  48 0 jupiter),
    rotate (60 * t /  29.46) (translate  89 0 saturn),
    rotate (60 * t /  84.32) (translate 178 0 uranus),
    rotate (60 * t / 164.80) (translate 279 0 neptune)
    ]

sun     = color orange         (circle 69)
mercury = color (dark white)   (circle 0.25)
venus   = color (light yellow) (circle 0.6)
earth   = color (light blue)   (circle 0.63)
mars    = color (dark orange)  (circle 0.34)
jupiter = color (light orange) (circle 7.1)
saturn  = color (light yellow) (circle 6.0)
uranus  = color azure          (circle 2.6)
neptune = color blue           (circle 2.5)

Here’s the tree example from the the gloss-examples package.  Unfortunately, it pegs the server’s CPU at 50%… so I’ll have to work on what’s making it run so slowly.

import Graphics.Gloss

animation :: Float -> Picture
animation time
	= Scale 0.8 0.8 $ Translate 0 (-300)
	$ tree 4 time (dim $ dim brown)

-- Basic stump shape
stump :: Color -> Picture
stump color
	= Color color
	$ Polygon [(30,0), (15,300), (-15,300), (-30,0)]

-- Make a tree fractal.
tree 	:: Int 		-- Fractal degree
	-> Float	-- time
	-> Color 	-- Color for the stump
	-> Picture

tree 0 time color = stump color
tree n time color
 = let	smallTree
		= Rotate (sin time)
		$ Scale 0.5 0.5
		$ tree (n-1) (- time) (greener color)
   in	Pictures
		[ stump color
		, Translate 0 300 $ smallTree
		, Translate 0 240 $ Rotate 20	 smallTree
		, Translate 0 180 $ Rotate (-20) smallTree
		, Translate 0 120 $ Rotate 40 	 smallTree
		, Translate 0  60 $ Rotate (-40) smallTree ]

-- A starting colour for the stump
brown :: Color
brown =  makeColor8 139 100 35  255

-- Make this color a little greener
greener :: Color -> Color
greener c = mixColors 1 10 green c
August 16, 2011 / cdsmith

Haskell For Kids: Week 1!

And We’re Off!

Thanks again to everyone that’s supported this project and stepped up to be a part of it.  Today, I taught my first in-person class on Haskell, and it was a blast!  This is my first weekly summary post, containing what we’re doing this week.

First: Introductions

Since there are a number of kids following along with this, let’s all get started with some introductions!

  • Me: My name is Chris Smith, and I’m teaching the in-person programming class at Little School on Vermijo that got all of this started.  I’m a huge fan of Haskell, and am really excited to be able to share that with new people!

  • Sue: Sue Spengler is the “founder, lead teacher, principal, superindendent, custodian, secretary, and lunch lady” for the Little School on Vermijo.  The school is her project, and she’s doing some pretty amazing things.  I had to poke around a bit for a photo, so I hope she likes this one!
  • My local students: The kids in my class today were Grant, Sophia, Marcello, and Evie (I hope I spelled that right!)  I’ll ask them to introduce themselves in comments on this post, so look for them there!
  • Everyone else: Any other kids who are taking the class, please use the comments to introduce yourselves as well!  You can say hello, and if you like, you can even link to a video or  picture.

I hope everyone takes the time to leave comments and say hello to each other.  Learning things is a lot more fun when you talk to other people.

The Plan

We talked about where we’re going, including:

  1. Write computer programs to draw pictures.
  2. Change our computer programs so the pictures move!
  3. Build a game of your own choosing.

This will take the school year!  That’s because this class isn’t just about memorizing some thing about a particular computer program: it’s about being creative, trying things, and doing something you’re proud of.  So there will be a lot of free time to play around and try out different ideas in your programs.  We are learning the Haskell programming language, but in the end, the class is more about being in control of your computer and designing and building something really cool from scratch, not just remembering some stuff about Haskell.

Organization of Computers and Programming

The first thing we talked about was what a computer program is, and how some of the ideas fit together.  Here’s the whiteboard when we were done!

Some of the ideas we talked about:

  • How a computer works.  The main part of a computer is built from a device for following instructions (the “CPU”), and a device for remembering information (“memory”).
  • Machine language.  The computer doesn’t speak English, of course!  It follows instructions in a language called “machine language”.  This language is easy for the computer to understand, but it’s very, very difficult to write programs in.
  • Compilers.  Instead of writing our programs in machine language, we write them in other languages, and then get the computer to translate them for us!  The program that does that is called a compiler.
  •  Some programming languages.  We have a choice what programming language to use when writing computer programs!  We brainstormed some languages kids in the class had heard about: Java, C, C++, Objective C, JavaScript, Java, and Smalltalk.  (Yes, Marcello had heard of Smalltalk!  I’m very impressed.)  The language we’re learning in this class is called Haskell.
  • Libraries.  Libraries are pieces of programs that other people have written for us, so we don’t have to start from scratch.  We spent some time imagining all of the steps involved what we might consider very easy things to do with a computer.  For example, thing of all the little steps in drawing a window… how many circles, rectangles, lines, letters, and so on can you find in a window on your computer?  Libraries let someone describe things once instead of making you repeat all that each time.

We talked about how we’ll be using:

  1. A programming language called Haskell.
  2. A library called Gloss.

Playing Around

At this point, we all used a web site to write some simple computer programs using Haskell and Gloss.  The web site is:

http://dac4.designacourse.com:8000/

We started out with some really simple programs, like these:

Draw a circle!

import Graphics.Gloss
picture = circle 80

Draw a rectangle!

import Graphics.Gloss
picture = rectangleSolid 200 300

Draw some words!

import Graphics.Gloss
picture = text "Hello"

All of these programs have some things in common:

  • The first line of each one is “import Graphics.Gloss”.  This tells the compiler that you want to use the Gloss library to make pictures.  You only need to say it once, and it has to be at the very beginning of your program.
  • They all then go on to say “picture = …”.  That’s because the way our programs work is to make a picture, and call it “picture”.  The web site we’re using then takes that picture, whatever we define it to be, and draws it for us.  We talked about how in the future, we might define other things with other names, but for now, we’re okay with just telling the compiler what “picture” is.
  • After the “=”, they describe the picture that we want to draw.  There are several types of pictures, and we’ve just seen three of them!  All of the kinds of pictures you can create are part of the Gloss library.
  • Except for the last one, they all use some distances.  For example, the 80 in the first example is the radius of the circle (the distance from the middle to the outside).  You can make that number larger to draw a bigger circle, and smaller to draw a smaller circle.  You can do the same with the width and height of the rectangle.

We did have problems with some people using the web site.  If you’re having trouble, you might need to make sure you have a new version of your web browser.  Also, the web site doesn’t work with Internet Explorer… so try with Chrome, Firefox, Opera, or Safari.  Don’t worry too much about the web browser problems: soon enough, you’ll install the Haskell compiler on your own computer, and you won’t need the web site to run your programs any more!  We’re just using the web site to get started quickly.

Drawing more than one thing!

By this time, several kids were asking if they can draw more than one shape at a time.  Yes, you can!  To draw more than one thing, you can use “pictures” (notice the s at the end).  For example,

import Graphics.Gloss
picture = pictures [
    circle 80,
    rectangleWire 200 100 ]

Notice we do this:

  • The word “pictures”
  • An opening square bracket.
  • A list of the pictures we want to draw, separated by commas.
  • A closing square bracket.

We talked about how it helps to make new lines in your program sometimes.  The only think you need to be careful of is that when you make a new line, you have to put a few spaces at the beginning to indent it.  See how the second and third lines of the part where we define “picture” are indented a little?

Changing your pictures

The Gloss library gives you some ways you can change your pictures, too!

You can change the colors with “color”.

import Graphics.Gloss
picture = color red (circleSolid 80)

Notice how you say “color”, then the name of the color you want, and then the picture to draw, in parentheses.  The parentheses are important!  They mean the same thing they do in math: treat that whole part as a single “thing” (in this case, a picture).

We talked about what colors Gloss knows about.  Here’s the list: black, white, red, green, blue, yellow, magenta, cyan, rose, orange, chartreuse, aquamarine, azure, and violet.  We all laughed because Sue picked a weird color name off the top of her head, and asked “Does it know chartreuse?”  Yes, it does.  Lucky guess!

You can also move things around on the screen.

import Graphics.Gloss
picture = translate 100 50 (rectangleSolid 50 50)

When you want to move things around, Gloss calls that “translate”.  Yes, it’s a weird name, but “translate” just means move something left, right, up, or down.  The first number after translate is how far to move it to the side.  Positive numbers mean right, negative numbers mean left, just like a number line!  The second number is how far to move it up or down.  Positive numbers mean up, and negative numbers mean down.

Keep in mind that in Haskell, you have to write negative numbers in parentheses!  If you say “translate -100 …”, then Haskell thinks you want to subtract one hundred from “translate”.  It doesn’t know how to subtract a number from a verb (I don’t either) so it gives up!  You have to write “translate (-100) …” instead, with the parentheses.

You can also turn things.  The verb for that is “rotate”.  Let’s draw a diamond.

import Graphics.Gloss
picture = rotate 45 (rectangleWire 100 100)

You rotate things in degrees.  Remember that 360 degrees means turn it all the way around to where it started, so it won’t do anything!  45 degrees is half of a right angle.  Do you see why that gives you a diamond?

The last thing you can do is stretch the picture.  The verb for that is “scale”.

import Graphics.Gloss
picture = scale 2 1 (circle 100)

That will draw an ellipse, which is like a circle but it’s wider than it is tall!

Don’t worry if this all doesn’t make sense yet!  We’ll be spending a lot of time playing around with how to put these things together!  Here’s the whiteboard after we finished all of this…

Time for Experimentation

We spent a lot of time with everyone making their own shapes and pictures of whatever they want.  The best way to get more comfortable with all of this is to play around.  Make lots of little changes and see what happens!  Try to guess what’s going to happen, then try it and see if you’re right or wrong.

Here are some pictures of the kids with their projects:

Sophia and Evie showing off two circles side by side.  These eventually became the eyes in a face!

That’s Grant with his diamond.  It looked even better after he stretched it a little bit up and down.

This was Marcello’s graphics… centering the word in the circle was a long task!  If you try it, you’ll notice text doesn’t get normally drawn right in the middle like other pictures do, so Marcello put in a lot of trial and error time with “translate” to put the word in the circle.

That’s Sophia being very excited at getting her two eyes in the right places!

Your Assignment

Your mission, if you choose to accept it… is to plan and create a drawing of something you’re interested in!  Maybe it’s a fish, a garden, a space station, or a dragon… just make sure you can draw it by using rectangles and circles of different colors, and moving, turning, or stretching them.  Here at the Little School, we’ll be spending our remaining class this week and our classes next week working on this.  Spend some time and come up with something you’re proud of!

August 15, 2011 / cdsmith

Haskell For Kids: Web-Based Environment Goes Public!

Last time, I described my work on a web-based programming environment for Haskell and Gloss, which is available from github as the gloss-web project.  Now you can try it online without having to install it yourself!  Here’s the URL:

http://dac4.designacourse.com:8000/

It seems to work fine at least with Chrome, Firefox, and Safari on Linux and Windows.  Internet Explorer (even 9) is known NOT to work.

What’s New

I’ve made a few changes to the code and fixed a number of bugs from Sunday’s late-night coding sprint, but the biggest change was to enable use of the SafeHaskell extension.  It’s now impossible to circumvent the type system and run arbitrary code on the server.  Evidence:

Note that there are still no resource or CPU time limits, so there are no protections against writing infinite loops or infinite data structures, so it’s still possible to use the server to run a denial of service attack against itself.  Please don’t do that.  I already know you can, and it’s really just not cool.  I’ve installed the server on a dedicated otherwise-empty machine I set up and installed for this purpose, so the only people you’ll really be hurting are other programmers like yourself who want to try this demo.

Want a non-trivial example to try it with?  Your wish is my command; here’s the simple one I’ve been playing around with as I develop the server:

{- This is my wagon -}

import Graphics.Gloss.Data.Picture
import Graphics.Gloss.Data.Color

picture = pictures [
    blank,
    color brown (translate (-60) (-80) wheel),
    color brown (translate ( 60) (-80) wheel),
    color black (translate (100) ( 75) (rotate 45 handle)),
    color red body
    ]

brown = dark (dark (dark orange))

wheel = pictures [
    rotate   0 spoke,
    rotate  45 spoke,
    rotate  90 spoke,
    rotate 135 spoke,
    rim
    ]

spoke = rectangleSolid 10 70

rim   = thickCircle 35 15

body  = rectangleSolid 200 100

handle = pictures [ rectangleSolid 100 10,
                    translate 50 0 (rectangleSolid 10 30) ]

Edit: Here’s something a little less trivial: a recursive drawing of a Koch snowflake.

import Graphics.Gloss

picture = kochSnowflake 4

kochSnowflake n = pictures [
    rotate   0 (translate 0 (-sqrt 3 * 100 / 6) (kochLine 100 n)),
    rotate 120 (translate 0 (-sqrt 3 * 100 / 6) (kochLine 100 n)),
    rotate 240 (translate 0 (-sqrt 3 * 100 / 6) (kochLine 100 n))
    ]

kochLine k 0 = line [(-k/2, 0), (k/2, 0) ]
kochLine k n = pictures [
    translate ( k/3) 0 (kochLine (k/3) (n-1)),
    translate (-k/3) 0 (kochLine (k/3) (n-1)),
    translate (-k/12) (-sqrt 3 * k/12) (rotate 300 (kochLine (k/3) (n-1))),
    translate ( k/12) (-sqrt 3 * k/12) (rotate  60 (kochLine (k/3) (n-1)))
    ]

You can find complete documentation for the gloss package, of course, at http://hackage.haskell.org/package/gloss.  Note that the server currently only implements the equivalent of displayInWindow, and rather than using the I/O action (which you can’t do, since SafeHaskell won’t let you do anything but purely functional code), you just define a top-level symbol called “picture” in your module.

Thoughts on SafeHaskell

Overall, I’m thrilled to have the SafeHaskell stuff in GHC.  It just has so many potential uses… it’s Java-style sandboxing, but at compile time!

There is one thing that confuses me, though… in order to get this working, I had to patch the gloss library to add “Trustworthy” declarations.  This is not ideal, for two reasons:

  • There are plenty of Haskell modules out there that GHC could easily prove are safe: if nothing else, just try to build them with the Safe extension, and if it fails, try again without it.  The vast, vast majority of Haskell packages would pass this test, and become available for use in safe code.  But that doesn’t seem to be what happens.  A module isn’t considered safe unless it’s explicitly specified to be safe, at compile time.  That greatly reduces the amount of code it’s possible to use from safe code, and sets up a huge obstacle in the way of getting a usable safe code ecosystem.
  • Even worse, in order to make this feasible at all, I had to declare gloss not just safe, but trustworthy.  I really shouldn’t have done that, since I haven’t vetted all of the gloss code to ensure that it doesn’t let you do bad stuff.  I really wanted GHC to assume that proof obligation, but instead I did myself.  Why?  Well, if I’d made it safe, I would have had to declare this for only certain modules (a much more intrusive change) and transitively go modify and rebuild all the pure code that gloss depends on, and so on down the dependency tree.

Perhaps I missed something, but if GHC is missing the opportunity to decide for itself when a module is safe, that’s a real shame, and something that will stand as an obstacle in the way of plenty of much more interesting and grander uses of SafeHaskell.

Anyway, that’s it for now!  Have fun playing…

August 14, 2011 / cdsmith

Haskell For Kids: A Web-Based Environment

In a comment on my last post here, Matthias Felleisen made the comment that it might be possible to make the first week or two of the Haskell for Kids effort go better if there were a web-based environment available.  After some thought, I’ve set out to create such a thing, and I’ve got an afternoon’s worth of proof of concept put together now.  Here, I’ll explain what it is, what the status of it is, and how it works.

WARNING!

Before I say any more, let me point out that you need to be very careful about running the code I’m talking about.  It’s in its very early stages, and the project involves running arbitrary other people’s code on your computers.  Obviously, that’s just a bit dangerous.  In particular,

  • Do not run this code on any system containing sensitive information, like SSL private keys, personal information, etc.
  • Do not run this code on a public network where untrusted people might be connecting.
  • Do not run this code if you have enemies who know you’re doing it, or friends with a malfunctioning sense of humor…

The medium-term plan is to use GHC 7.2′s SafeHaskell extension, along with a reasonable set of resource limits, to run code safely and prevent access to unsafePerformIO and friends.  This is not part of the code yet, so for now it’s very, very unsafe.

Introducing the gloss-web package…

If you look at https://github.com/cdsmith/gloss-web, you’ll find a small amount of initial code toward a web-based environment for Haskell programming in Gloss.  It includes:

  • A web-based editor with syntax highlighting for Haskell, based on Cloud9′s ACE editor.
  • A compilation server that compiles, builds, and runs programs.
  • A JavaScript and JSON-based rendering system for viewing the resulting images.

In short, it’s everything you need to build pictures using Gloss without a local installation of Haskell.

Don’t take this as saying that you can completely skip installing Haskell for the class that’s starting in a few days.  In the end, that’s probably a bad idea.  But in a few situations (particularly in my in-person class, where getting GHC installed on everyone’s computers is likely to take some time), it may help rather a lot to have the ability for students to run their first programs in a web-based system.

Keep in mind that if you’re helping just one kid, as many blog readers are planning on doing, then this is probably a waste of your time.  Just install Haskell on the computer your kid is using instead!

What does it look like?

Good question!

How to Install

I have not released this on Hackage yet, because it’s in very, very early stages.  But you can download it from the github URL above and install it as follows.

  • Download the current code from github
  • Change into the directory and type ‘cabal install’.
  • Type ‘gloss-web’ to run.

You’ll need some relatively recent version of the Haskell Platform to get it working.  If you’re having problems, feel free to ask for help.

Want to Help?

For any experienced Haskell programmers out there who are interested in helping out, patches would be great!  I’ve got plans, and do intend to do them on an as-needed basis as the year-long class proceeds (three cheers for “lazy” evaluation!), but I’m also happy to accept patches from anyone else.

Some of the outstanding challenges include:

  • Test and get it working in more web browsers.  Currently it runs fine in Chrome, and I hope to have no major issues in Firefox or Safari, but I imagine IE will be a whole new ball game.
  • Add a better way to load images, since you can’t use the IO monad.  One thought I have is to let you upload images, and then throw in a built-in module called Images that can be imported that (via unsafePerformIO) defines symbols for each uploaded image.
  • Use SafeHaskell in GHC 7.2, or some other mechanism, to enforce safe execution and prevent use of Template Haskell, unsafePerformIO, the FFI, or any other tricks to get around the type system and run arbitrary code.
  • Implement resource limits and timeouts in case of badly behaved programs.
  • Add support for the animation, simulation, and game interfaces of gloss.  This will involve some kind of streaming from the server via XMLHTTPRequest or some such thing.
  • Better organization of the code.  This will probably use Snap 0.6 extensions, so I’m just keeping it working until that’s released.

I’m particularly interested in getting some of the safety issues handled, as that’s a prerequisite to running this publicly (currently I will be running it locally only for my local class).  The rest of it would be awesome too, though!

Enjoy!

August 13, 2011 / cdsmith

Arrow = Category + Applicative? (Part IIa)

I’m labeling this part (II a), because I haven’t got everything I wanted to finish for this piece, but there are enough interesting ideas that it’s worth posting something, and enough time has passed that I’m getting people asking about the next part!

Summary So Far

In the previous installment of this series, we established a one-way relationship between Applicative and Arrow, while assuming a common Category instance.  In particular, we assumed a data type

data a :~> b = ...

and instances

instance Category (:~>) where
    id    = ...
    (.)   = ...
instance Arrow (:~>) where
    arr   = ...
    first = ...

and satisfying the axioms

[C1] f                            = f . id
                                  = id . f
[C2] f . (g . h)                  = (f . g) . h
[A1] arr   id                     = id
[A2] arr   (f . g)                = arr f   . arr g
[A3] first (f . g)                = first f . first g
[A4] first (arr f)                = arr (f `cross` id)
[A5] first f . arr (id `cross` g) = arr (id `cross g) . first f
[A6] arr fst . first f            = f       . arr fst
[A7] arr assoc . first (first f)  = first f . arr assoc

And we showed that we can always write the following Applicative instance, universally quantified over any domain for the Category:

instance Applicative ((:~>) a) where
    pure x  = arr (const x)
    f <*> x = arr (uncurry (flip ($)))
            . first x
            . arr swap
            . first f
            . arr dup

And, furthermore, that it will automatically satisfy all four of the axioms for Applicative functors.

[F1] v                 = pure id <*> v
[F2] u <*> (v <*> w)   = pure (.) <*> u <*> v <*> w
[F3] pure f <*> pure x = pure (f x)
[F4] u <*> pure y      = pure ($ y) <*> u

This demonstrates that Arrow is at least as specific as the combination of Category and a universally quantified Applicative instance: if you have the first, then you automatically have the second as well.  We now want to explore the opposite direction…

The Inverse Correspondence

We will need a specific Arrow instance now to work with, defined in terms of an arbitrary Applicative instance.  Here’s the one we’ll be using:

instance Arrow (:~>) where
    arr f   = pure f <*> id
    first f = pure (,) <*> f . arr fst <*> arr snd

I’ll again try to convince you that these definitions make logical sense.  Keep in mind the following,

pure f <*> x = f <$> x = fmap f x

So the definition of arr is very general: it doesn’t even really need Applicative — just Functor.  That ought to be comforting, since in a sense all that Functor says is that we can naturally translate from pure Haskell functions to a different context.  It’s not surprising that there would be a strong connection between the lifting of functions given by fmap, and that given by Category and Applicative.  Indeed, arr is that connection.  The Category “id” value on the right of the fmap serves to tie the input from the Category with the input to the function f, giving precisely what we want: a lifting of f into the Category.

Another way to understand arr’s definition is to recall that in the ((->) t) functor, whose objects are just Haskell functions from a fixed domain type, fmap is precisely function composition.  The functor we have here looks very close to that one, and indeed, fmap has a similar meaning.  The difference is that in our applicative functor, fmap composes pure Haskell functions not with other functions, but with morphisms in our Category, giving a morphism as the result.  Lifting a function is done by composing it with the identity morphism.

The definition of first is basically self-evident if you’re familiar with Applicative.  If you’re confused, note that (.) binds more tightly than <*>… we’ll be using that a lot.  So this just unpacks a tuple, applies the given Category element on the left, and packs it back up using the tuple constructor.

Failure

Our stated goal was that by defining the correspondence above, things will just work out and we’ll have established that all of the axioms for Arrow hold.  This should be easy to check!  The Applicative laws give us a really nice tool to reason about equivalence of two expressions.  You may note that I’ve stated them slightly differently here, versus the previous post, by swapping the sides of a few of them.  You should read the four axioms [F1] through [F4] as having a natural left to right direction to them, and by applying each of them as appropriate, we can take any Applicative expression and obtain a normal form:

pure f <*> x_1 <*> x_2 <*> ... <*> x_n

Here, none of x_1 through x_n contain any applicative building blocks (pure or <*>, or any of the constants built from them like fmap, etc.)  Category also has such a normal form, where any expression from a category can be written as either a single identity, or a sequence of composed morphisms, with no other identities or composition occurring in the pieces:

f_1 . f_2 . ... . f_n

What about mixtures of the two?  We have no laws at all that allow us manipulate expressions across the two types, so we’re stuck with the pieces as they are, simplifying within each piece. So to verify the axioms, we simply substitute the definitions of arr and first from the previous section, reduce the Applicative and Category pieces to their respective normal forms, and compare.  Easy, right?

It’s left as an exercise for the reader to try this, but the result is that only the trivial axiom [A1] can be verified in this way.  The remaining Arrow laws do not follow from anything we’ve seen so far. It’s not just that we aren’t clever enough to do it: because both Applicative and Category have normal forms, and there’s no mixing of the two possible, it’s simply not possible that any more of the Arrow laws might be shown to hold all the time from those laws alone!  (This in spite of the fact that numerous source, such as here, explicitly claim otherwise!)

Dodging a Dead End Sign: New Laws!

In a strict sense sense, this is the end of the line: our original goal has conclusively failed.  That said, it’s not so surprising that it failed, and we can still learn a lot by redefining our goal.  We now seek to decide precisely what the difference is.

That is, can we state a (hopefully minimal) set of additional laws we can apply to the Applicative/Category combination, such that we can get all of the Arrow axioms? We’re looking for things that obviously ought to hold for all types that are simultaneously instances of Category and Applicative.  Of course, we’ll also have to go back and show that they follow from the Arrow axioms as well, or we risk losing the bidirectional correspondence.  It’s worth noting that Ross Patterson speculated about such axioms, and that while my axioms look a bit different, if you dig a bit they turn out to very very similar)

Here are the set of axioms I’ll propose:

[G1] u = pure const <*> u <*> id
[G2] u <*> id <*> id = pure join <*> u <*> id
[G3] arr f . u = pure f <*> u
[G4] (u <*> v) . arr f = u . arr f <*> v . arr f

A couple quick notes.  First of all, you might notice that the Arrow term, arr, appears in a couple of them.  That’s okay, though: we don’t mean arr in the Arrow sense.  We mean it in the sense of the definition earlier, as an fmap applied to the identity from the Category.  It turns out that arr plays a unique role in the structure we get from combining Category and Applicative.  It’s a sort of intermediate level of purity between “pure” elements and arbitrary elements.  The elements in the image of arr are pure in the sense of acting like plain functions in the Category, but they depend on the domain type from the Category, making them not quite “pure” in the Applicative sense.  It’s useful to make statements about elements with that half-purity property.

Second, you might notice a use of “join” in [G2], which is of course a Monad term!  Never fear, though, we mean join specialized to the ((->) r) monad, which is just the function:

join f x = f x x

So no worries, we haven’t let monads creep in quite yet!  The connection here is very strong though, and is strengthened by noting that “const” is similarly just “return” specialized to the ((->) r) monad, and together, return and join completely determine the monad structure on a type!  So in a sense, laws [G1] and [G2] are relating the structure we’ve got to monad terms… but the monad is the standard function monad instead of one defined on this type.

Having gained a little insight into [G1] and [G2], we now look at the laws [G3] and [G4].  These laws address the question of what happens when we compose an arr value, either on the left or right.  Essentially, arr composed on the left can be rewritten in terms of application, while on the right it distributes.

Let’s Prove Some Arrow Laws

One of the Arrow laws is so obvious, there’s no point in putting off its proof any longer; it turns out to be exactly equivalent to the first Applicative axiom, and is the one Arrow law that didn’t require our new assumptions:

arr id = pure id <*> id = id

Now, before we set out to methodically prove that Arrow axioms hold, it pays to look around and take stock of the situation with the new laws one at a time.

We can start out by generalizing [G1] and [G2] a bit.  As stated, these laws require identities on the right-hand side, but it turns out they actually only need semi-pure (that is, arr) values.  To see this, we’ll first prove a little lemma, which actually only requires the Applicative laws:

u <*> arr f = u <*> (pure f <*> id)
            = pure (.) <*> u <*> pure f <*> id
            = pure ($ f) <*> (pure (.) <*> u) <*> id
            = pure (.) <*> pure ($ f) <*> pure (.) <*> u <*> id
            = pure (($ f) . (.)) <*> u <*> id
            = pure (. f) <*> u <*> id

With that in our toolkit, we generalize [G1] and [G2] in the obvious way, just by moving arr values from the right to the left, and then moving the parentheses left.  It’s a tad cumbersome, but pretty obvious when you see what’s going on.

pure const <*> u <*> arr f
    = pure (. f) <*> (pure const <*> u) <*> id
    = pure (.) <*> pure (. f) <*> pure const <*> u <*> id
    = pure ((. f) . const) <*> u <*> id 
    = pure const <*> u <*> id
    = u
u <*> arr f <*> arr f
    = pure (. f) <*> (u <*> arr f) <*> id
    = pure (. f) <*> (pure (. f) <*> u <*> id) <*> id
    = pure (.) <*> pure (. f) <*> (pure (. f) <*> u) <*> id <*> id
    = pure ((.) (. f) <*> (pure (. f) <*> u) <*> id <*> id
    = pure (.) <*> pure ((.) (. f)) <*> pure (. f) <*> u <*> id <*> id
    = pure ((.) (. f) . (. f)) <*> u <*> id <*> id
    = pure join <*> (pure ((.) (. f) . (. f)) <*> u) <*> id
    = pure (.) <*> pure join <*> pure ((.) (. f) . (. f)) <*> u <*> id
    = pure (join . (.) (. f) . (. f)) <*> u <*> id
    = pure ((. f) . join) <*> u <*> id
    = pure (.) <*> pure (. f) <*> pure join <*> u <*> id
    = pure (. f) <*> (pure join <*> u) <*> id)
    = pure join <*> u <*> arr f

These identities can be very useful: they avoid the need to explicitly “stash away” semi-pure values on the right when applying the first two laws.  Note that the values on the right obviously need to be semi-pure, since otherwise we could be removing or duplicating effects (where “effects” here has the appropriate meaning for the particular instance you’re looking at).

Another convenient thing to note is that anywhere we use “arr” to indicate a semi-pure value, of course a pure value works too!  The following mini-identity makes this explicit:

pure x = pure const <*> pure x <*> id
       = pure (const x) <*> id
       = arr (const x)

We can now turn to the [G3] law, and see what insights it has to offer.  The first is actually one of the Arrow laws, but it’s also quite useful in reasoning about other things as well:

arr (f . g) = pure (f . g) <*> id
            = pure (.) <*> pure f <*> pure g <*> id
            = pure f <*> (pure g <*> id)
            = pure f <*> arr g
            = arr f . arr g

As an immediate consequence, we can simplify compositions involving pure and semi-pure values.

pure x . arr f = arr (const x) . arr f
               = arr (const x . f)
               = arr (const x)
               = pure x

A more broadly applicable set of identities lets us work with applications between pure values and compositions (of any values at all):

pure f <*> u . v = arr f . (u . v)
                 = (arr f . u) . v
                 = (pure f <*> u) . v
u . v <*> pure f = pure ($ f) <*> u . v
                 = (pure ($ f) <*> u) . v
                 = (u <*> pure f) . v

So applying a pure value to a composition, or a composition to a pure value, is the same as doing the application only to the first of the two values that are composed.

We also have the tools now to easily establish another of the Arrow laws.  Since we’ve done it so many times by now, I’ll start applying the composition law from Applicative and combining the resulting pure expressions on the left in one step.

arr fst . first f
    = pure fst <*> first f
    = pure fst <*> (pure (,) <*> f . arr fst <*> arr snd)
    = pure ((.) fst) <*> (pure (,) <*> f . arr fst) <*> arr snd
    = pure (((.) fst) . (,)) <*> f . arr fst <*> arr snd
    = pure const <*> f . arr fst <*> arr snd
    = f . arr fst

For the next step, it helps to consider what happens when you apply (with <*>) one semi-pure value to another.  The answer is reassuringly logical: Applicative’s <*> combinator can be specialized to functions, and the result goes by several names… Monad’s “ap”, for example, and combinatory logic’s S combinator.  Let’s use “ap” to describe the function we’re looking for:

(f `ap` g) x = f x (g x)

Then we have

arr f <*> arr g = arr f <*> (pure g <*> id)
                = pure (.) <*> arr f <*> pure g <*> id
                = arr (.) . arr f <*> pure g <*> id
                = pure ($ g) <*> arr (.) . arr f <*> id
                = arr ($ g) . arr (.) . arr f <*> id
                = arr (($ g) . (.) . f) <*> id
                = pure (($ g) . (.) . f) <*> id <*> id
                = pure join <*> pure (($ g) . (.) . f) <*> id
                = pure (f `ap` g) <*> id
                = arr (f `ap` g)

That turns out to be the hard work in establish our fourth Arrow law.

first (arr f) = pure (,) <*> arr f . arr fst <*> arr snd
              = arr (,) . arr f . arr fst <*> arr snd
              = arr ((,) . f . fst) <*> arr snd
              = arr (((,) . f . fst) `ap` snd)
              = arr (f `cross` id)

Not bad!  Four Arrow laws down, three to go, and we haven’t even used our shiny new [G4] law yet.  We can fix that, though, and prove a fifth Arrow law in the process:

first f . arr (id `cross` g)
    = (pure (,) <*> f . arr fst <*> arr snd) . arr (id `cross` g)
    = pure (,) . arr (id `cross` g)
      <*> f . arr fst . arr (id `cross` g)
      <*> arr snd . arr (id `cross` g)
    = pure (,) <*> f . arr (fst . (id `cross` g)) <*> arr (snd . (id `cross` g))
    = pure (,) <*> f . arr fst <*> arr (g . snd)
    = pure (,) <*> f . arr fst <*> arr g . arr snd
    = pure (,) <*> f . arr fst <*> (pure g <*> arr snd)
    = pure (.) <*> (pure (,) <*> f . arr fst) <*> pure g <*> arr snd
    = pure ((.) . (,)) <*> f . arr fst <*> pure g <*> arr snd
    = pure ($ g) <*> (pure ((.) . (,)) <*> f . arr fst) <*> arr snd
    = pure (($ g) . (.) . (,)) <*> f . arr fst <*> arr snd
    = pure ((.) (id `cross` g) . (,)) <*> f . arr fst <*> arr snd
    = pure ((.) (id `cross` g)) <*> (pure (,) <*> f . arr fst) <*> arr snd
    = pure (id `cross` g) <*> (pure (,) <*> f . arr fst <*> arr snd)
    = pure (id `cross` g) <*> first f
    = arr (id `cross` g) . first f

Of course, this series just wouldn’t be itself if we didn’t have a long ugly proof in there somewhere, so here it is: the proof of [A7].

arr assoc . first (first f)
    = pure assoc <*> first (first f)
    = pure assoc <*> (pure (,) <*> first f . arr fst <*> arr snd)
    = pure ((.) assoc) <*> (pure (,) <*> first f . arr fst) <*> arr snd
    = pure ((.) assoc . (,)) <*> first f . arr fst <*> arr snd
    = pure (. snd) <*> (pure ((.) assoc . (,)) <*> first f . arr fst) <*> id
    = pure ((. snd) . (.) assoc . (,)) <*> first f . arr fst <*> id
    = pure ((. snd) . (.) assoc . (,))
      <*> (pure (,) <*> f . arr fst <*> arr snd) . arr fst <*> id
    = pure ((. snd) . (.) assoc . (,))
      <*> (pure (,) . arr fst <*> f . arr fst . arr fst
      <*> arr snd . arr fst) <*> id
    = pure ((. snd) . (.) assoc . (,))
      <*> (pure (,) . arr fst <*> arr fst . arr fst . first (first f)
      <*> arr snd . arr fst) <*> id
    = pure ((. snd) . (.) assoc . (,))
      <*> (pure (,) <*> arr (fst . fst) . first (first f)
      <*> arr (snd . fst)) <*> id
    = pure ((.) ((. snd) . (.) assoc . (,)) . (,))
      <*> arr (fst . fst) . first (first f) <*> arr (snd . fst) <*> id
    = pure (. (snd . fst)) <*> (pure ((.) ((. snd) . (.) assoc . (,)) . (,))
      <*> arr (fst . fst) . first (first f)) <*> id <*> id
    = pure (.) <*> pure (. (snd . fst))
      <*> pure ((.) ((. snd) . (.) assoc . (,)) . (,))
      <*> arr (fst . fst) . first (first f) <*> id <*> id
    = pure ((. (snd . fst)) . (.) ((. snd) . (.) assoc . (,)) . (,))
      <*> arr (fst . fst) . first (first f) <*> id <*> id
    = pure (\x y z -> (x, (snd (fst y), snd z)))
      <*> arr (fst . fst) . first (first f) <*> id <*> id
    = pure join <*> (pure (\x y z -> (x, (snd (fst y), snd z)))
      <*> arr (fst . fst) . first (first f)) <*> id
    = pure (\((a,b),c) ((d,e),f) -> (a, (e, f))) <*> first (first f) <*> id
    = pure (. (snd `cross` id))
      <*> (pure (,) <*> (pure (fst . fst) <*> first (first f))) <*> id
    = pure (. (snd `cross` id))
      <*> (pure (,) <*> arr (fst . fst) . first (first f)) <*> id
    = pure (. (snd `cross` id))
      <*> (pure (,) <*> f . arr (fst . fst)) <*> id
    = pure (,) <*> f . arr (fst . fst) <*> arr (snd `cross` id)
    = pure (,) . arr assoc <*> f . arr fst . arr assoc <*> arr snd . arr assoc
    = (pure (,) <*> f . arr fst <*> arr snd) . arr assoc
    = first f . arr assoc

Not pretty, by any stretch of the imagination, but it’s done.

To be continued…

Quite a bit remains here: we still have one Arrow law remaining, we need to show that our four new Category+Applicative laws follow from the Arrow axioms in the other direction, and we need to show that the maps we’ve defined between Applicative and Arrow are inverse to each other.  With luck, this and more will come in the next exciting installment.

August 7, 2011 / cdsmith

An Invitation for Kids to Learn Programming

I wrote in my last entry about the class I’m teaching this school year for kids learning programming in the Haskell programming language.  After the response there, I talked it over with people involved, and we decided to extend an invitation to other children to be “virtually” part of the class!

If you:

  1. Know a child who would be interested in learning programming, and
  2. Know something about computer programming, and know or are willing to learn the basics of Haskell

Then I’m inviting you and the child you know to join our journey for the year!  You’d be volunteering to do the teaching, but at least we can have a group of kids all learning at the same time.

Here’s what that means.

The Projects

We’ll work throughout the year on a sequence of increasingly involved projects involving computer graphics, ranging from drawing pictures to creating computer games.  I went into a lot more detail about the plan in the previous entry, so I encourage you to go back and read it if you didn’t before.

The key point here is that we want to provide several opportunities for kids:

  • The thrill of building something they are proud of, and getting a computer do what they want, rather than the other way around.
  • Practice in abstract thinking that will prepare them for mathematics, logic, and life in general.

It’s not really a goal at all to prepare students for a computer programming career, nor to teach the programming language we’ll be using (Haskell) in any comprehensive sense.

The Community

First of all, everything we do in the class will be summarized on this blog, in posts in the “Haskell for Kids” category.  My students will be assigned to come leave comments on each post with questions, comments, or thoughts they have about what we did that week.  We encourage you and the child you’re working with to do the same.  Please respond to each other’s posts, and talk about what you find interesting as well.  Our hope is that not only will everyone learn programming, but that we’ll also be able to build a community of kids who know each other and care about each other’s accomplishments.

One of the things we’ll be doing the first week (which is next week.., wow!) is recording videos where students introduce themselves and talk about what they hope to get out of this.  We’ll put these on YouTube, and I’ll embed them in the first blog post.  Any other children participating are encouraged to do the same.  If you leave a link to your own video, I can embed it in that post as well!

I tend to be in favor of letting people have awesome experiences, rather than obsessing about safety… but a few common-place restrictions are needed here.  Please don’t post comments in the Haskell for Kids category with profanity, insults, etc.  Let’s be a supportive community.  Please also make sure kids don’t post phone numbers, addresses, or other contact information that really could compromise their safety.  I’ll be watching comments on these posts a little more closely than the rest of this blog, and  I will try to actively remove comments that are problematic, more than I do elsewhere.

Sharing Projects

One of the really cool aspects of this is that we’ll be building stuff — in the beginning pictures, then animations, and finally games!  It’s way more fun to share the stuff you’re building with others.  So I’ve set up a version control repository for all the kids’ projects.  The goal here is to let people easily get, compile, and try out the projects of others.  I’ll be happy to add anyone else that’s participating as a committer, so that you can add your students’ projects to the group, too; just ask in a reply to your child’s comment introducing themselves, and ask.

For anyone that doesn’t want to figure out how to set up darcs or use version control, you’re also welcome to email me your child’s source code in a zip file, and I’ll handle getting it checked in; but there might be delays of a day or two before others can get your code if you do it that way.

Teachers

Every kid that’s participating will have a teacher: for the kids in the physical class, that’s me.  For the kid you know, that would be you!  I considered trying to set up a way for all of us teachers to talk to each other about lesson plans, feedback on what to do and what to spend more time on… but then I realized that there’s no real reason to be secretive about it!  We can use blog comments as well, and if kids read it and find it interesting, so much the better!

For rare (hopefully nonexistent) occasions where we really do need adult-only conversation, a lot of the people involved in this are already using Google+, so we can coordinate building up a mutual circle for adults involved in this project, and communicate there… if you want to be part of this, we’ll coordinate it after kids do introductory posts next week.

What Ages?

The students I’m teaching are in the 7th grade in U.S. terms, so about 12 years old, turning 13 during the school year.  Kids younger than that are always welcome to participate, as long as you (“you” meaning the responsible adult) feel like they will be able to keep up, or at least that it’s worth a try.  Kids older than that are welcome up to a point…

That point is defined by the idea that we want this to be a group of peers, and something that kids are doing for their personal development and fun.  I don’t want to set an age limit, but if I did, maybe it would be 14-15.  In the end, though, it depends on personality: some teens are happy to learn alongside younger kids and interact as peers, and some are not so happy about it.  And, if an older teen is learning programming as a possible job prospect, I wish them well but they are also not likely to find this the best way to do that.  You presumably know the child you’re thinking about, so feel free to make a judgement call!

Of course, children of any age — even those that are middle-aged, or collecting pensions — are welcome to read the blog, and pipe in with helpful comments and encouragement!

What Next?

My first in-person class will meet a week from Tuesday.  Sadly, a fair amount of the first two weeks is likely to be taken up with getting software installed: the Haskell Platform, for example, and a text editor, and becoming accustomed to using the console, changing directories, and typing commands.  We’ll also talk about the high-level ideas of compilers and programming languages and how they fit together, and play around with using GHCi as a calculator and with entering and running simple programs.

You can expect the first “real” blog post (the first one that follows an actual class) to appear Wednesday of next week, and that’s when we’ll ask kids to start commenting.  See you then!

August 3, 2011 / cdsmith

Haskell For Kids! Introduction

In a couple weeks, I’ll be posting a blog entry once a week called “Haskell for Kids”.  This is an introduction to what that’s all about.

What Is It, and Why?

I have the excellent chance this school year to teach Haskell to a group of children aged 12 to 13 years old!  I’m very excited about it.  I’m teaching the class as part of the Little School on Vermijo, which is a neighborhood school taught by my neighbor, Sue.  I love this concept: the school meets in her living room, it’s a very small class, and a lot of people in the neighborhood are pitching in with subjects here and there.  Last year, I taught a once-a-week mathematics class, which was really great.  This year, I’m trying programming for two hours per week.

Haskell?  Really?

Yes, I picked Haskell for a programming language.  That will be controversial, of course, but I think I have good reasons.

  • It’s something I’m excited about!  I think that’s bigger than a bunch of technical details: it’s important for everyone to teach what you’re excited about, and pass that excitement to others.
  • Ben Lippmeier’s Gloss library is an excellent educational tool.  It’s a library for building graphics-related programs with a high-level, composable, and semantically meaningful API.
  • I think Haskell is the best environment to learn and practice abstract patterns of thinking that will be useful in mathematics, logic, and a clear understanding of the world.  You see, I don’t care whether anyone comes out of this class headed for a computer programming career.  If they’ve got their heart set on being a poet, I hope to have contributed something valuable to their lives, too.

The objections I’ve heard when I’ve discussed the plan with others come down to Haskell being “hard”.  I think that’s an oversimplification.  If you look at the reasons Haskell is considered “hard”, a lot of it comes down to: (a) it’s different from other languages that people are used to, and (b) people are doing hard things with it.  Neither objection applies in this class.

That’s not to say that Haskell ought to be everyone’s choice.  If you’re looking at teaching programming to children, I think the most important thing is to avoid incidental complexity.  Any language that lets you get right to talking about what you want to do is suitable.  If I weren’t doing this in Haskell, I’d be choosing Python.  But excitement matters, so Haskell it is.

What’s Blogs Got To Do With It?

The actual class will be happening two mornings a week on Tuesday and Wednesday.  In the process of planning, though, I ran into the inevitable problem that there aren’t really any textbooks for teaching Haskell programming to 12 year olds!  So in lieu of a textbook, here’s my plan:

  1. Of course, I’ve done some preparation: made an outline of several dozen topics, and mapped out the dependencies between them, and ideas for exercises in Gloss that might accompany each one.  I don’t intend to share this, though, because I want to avoid locking in to a pace or syllabus before we even get started.
  2. Each week, directly after that week’s two classes, I’ll write up my notes of what we talked about, and publish them in that weeks’ Haskell for Kids blog entry as a review.
  3. My students will be assigned to come comment with specific questions they have, or with comments on things they found interesting, additional ideas that came to mind, or what they were able to do with their programs that seemed cool.

I hope to accomplish a couple things with that structure.

The first, and least interesting, is to have a written source for anyone in the class that wants to go back and review topics from the past.  To be honest, I hope this isn’t very common.  If I’ve got people needing to constantly go back and copy code from past lessons, then I think that’s a pretty good indication I’m going too fast!  That said, though, it will be nice to have the notes available, especially for students who are absent or just find it useful to go back and read it again.

The second, and more important, thing I hope to accomplish is to connect students in this class with a larger community.  Anyone else reading this blog, whether you’re learning Haskell or a part of the community already, is encouraged to jump in the conversation and participate.  I know I’ve talked to at least three or four people, from when I originally asked around for experiences with this through now, who wanted to be kept up to date on how it goes, or even follow along.  This is your chance!

A Preview of the Class

I’m organizing the class around the structure of Ben’s Gloss library, which happens to be related to a nice progression of programming ideas as well!  So the best way to explain the structure will be to mention the four entry points in Gloss:

displayInWindow

This is the simplest of the four Gloss entry points: you give it a picture, and it displays the picture in a window.  We’ll use it to look at basic types of data (numbers, boolean values, etc.), structured types (for example, lists and tuples), expressions, precedence and order of operations, variables, and list comprehensions.

animateInWindow

This Gloss entry point displays an animation, represented as a function that maps the current time to a picture.  We’ll use it to talk about defining functions, conditionals, pattern matching, and type declarations.

simulateInWindow

The third Gloss entry point runs a simulation, which differs from an animation in that it maintains a state.  We will use it to discuss defining and operating on our own data types.

gameInWindow

The fourth and final Gloss entry point runs a simulation with user input, which is suggestively called a game.  We’ll use this to talk about issues arising in larger-scale programs: recursion in both code and data, modular programming, simple data structures, and building complex data types.  At this point, I also expect to transition even more toward providing time for practice, and encouraging everyone to create something of their own.

The exact time allocations for each part will be determined over the course of the year, so we’ll see how it goes!  If you’re interested, I hope you stick around.

Follow

Get every new post delivered to your Inbox.

Join 62 other followers