Skip to content

Instantly share code, notes, and snippets.

@kristopherjohnson
Last active August 12, 2020 22:13
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kristopherjohnson/2384d9dcd5ed744734f0 to your computer and use it in GitHub Desktop.
Save kristopherjohnson/2384d9dcd5ed744734f0 to your computer and use it in GitHub Desktop.
Towers of Hanoi in Haskell
#!/usr/bin/env runhaskell
-- Print sequence of moves for 4 discs from pin "A" to pin "C"
main = do putStrLn "Move stack of four discs from A to C:"
printNumberedList moves
where moves = hanoi 4 "A" "C" "B"
-- Return list of moves for moving stack of N discs from one pin to another
hanoi :: Show a => Int -> a -> a -> a -> [String]
hanoi 0 _ _ _ = []
hanoi count from to other = moveToOther ++ [moveBottomDisc] ++ moveFromOther
where
moveBottomDisc = (show from) ++ " -> " ++ (show to)
moveToOther = hanoi (count - 1) from other to
moveFromOther = hanoi (count - 1) other to from
printNumberedList :: [String] -> IO ()
printNumberedList xs = mapM_ printLine $ zip [1..] xs
where printLine (n, s) = putStrLn $ show n ++ ". " ++ s
@anohren
Copy link

anohren commented Jul 10, 2015

Thanks for this. I haven't touched Haskell, but thought I should learn so I decided to stare at this little piece of code until I could (?) understand it. I'm writing this down just to put words on it. This is what I got:

hanoi :: Show a => Int -> a -> a -> a -> [String]

Function declaration. Show a makes a type placeholder a which conforms to Show. All as must be of the same type. They can apparently be passed to show which returns a String. hanoi can be partially applied (don't know if that's the case with all functions in Haskell...) three times before returning a list of Strings.

hanoi 0 _ _ _             = []

Function definition. Matches all calls with first parameter of 0 and returns an empty list.

hanoi count from to other = moveToOther ++ [moveBottomDisc] ++ moveFromOther

Function definition. Matches all other calls. Calls three functions (?) and concatenates three lists with ++.

where
    moveBottomDisc = (show from) ++ " -> " ++ (show to)
    moveToOther    = hanoi (count - 1) from other to
    moveFromOther  = hanoi (count - 1) other to from

Definition of symbols in previous expression.

printNumberedList :: [String] -> IO ()

Function declaration. Takes a list of Strings and returns an IO. The () is hard to figure out...

printNumberedList xs = mapM_ printLine $ zip [1..] xs
  where printLine (n, s) = putStrLn $ show n ++ ". " ++ s

[1..] is an infinite list of integers starting at 1. mapM_: For each tuple in zip [1..] xs apply printLine. Can't figure out the $.

printNumberedList xs = (mapM_ printLine $ (zip [1..] xs))
  where printLine (n, s) = (putStrLn $ ((show n) ++ ". " ++ s) )

It's not a parameter. Parameter placeholder?

Time to sleep. Google later.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment