Planes, Airports, and Monads - Adventures in Haskell
2014-04-20 18:00
TODO is the smallest airport in the world, it can only hold 3 planes at any time.
You are the air traffic controller there, and your job is to plan the landings and taking off of all the planes so that no accidents happen.
This job is not too difficult, you just have to look at the landing and taking-off sequence, and determine if the airport can accomodate the sequence.
Let’s model that.
Planes can land, or take off:
land :: Planes -> Airport -> Airport
land incoming grounded = grounded + incoming
takeoff :: Planes -> Airport -> Airport
takeoff flying grounded = grounded - flying
We can try landing and taking off:
> takeoff 1 (land 2 0)
1
> takeoff 2 (land 3 (takeoff 1 (land 2 0)))
0
> `land` 2 `takeoff` 1 `land` 3 `takeoff` 2
2
The second example seems to be okay, but actually we had let 4 planes in the airport at once. Let’s fix that using Maybe
.
When we have too many planes, we return a Nothing
, meaning that this particular sequence can not be accomodated safely by the airport.
land :: Planes -> Airport -> Maybe Airport
land incoming grounded
| grounded + incoming > 3 = Nothing
| otherwise = Just (grounded + incoming)
takeoff :: Planes -> Airport -> Maybe Airport
takeoff flying grounded
| grounded - flying < 0 = Nothing
| otherwise = Just (grounded - flying)
Let’s try this:
> land 3 0
Just 3
> land 4 0
Nothing
> takeoff 2 0
Nothing
> takeoff 1 2
Just 1
Now we have a problem because we can no longer chain our land
and takeoff
methods together easily. They both return a Maybe Airport
, but they take in Airport
. We can try to write a function to take care of this.
chain :: Maybe Airport -> (Airport -> Maybe Airport) -> Maybe Airport
chain Nothing _ = Nothing
chain (Just grounded) action = action grounded
And we can now write things smoothly
> Just 1 `chain` takeoff 1 `chain` land 2 `chain` takeoff 2
Just 0
And if we just change the name of chain
to >>=
There we have it, the bind
operator in Monads!