I am really learning a lot doing your NICTA course on my own. Â The structure of your course is by far the best I have seen.
Questions:
- where/when do you give this course?
- how long does the course generally take?
- what supplemental material is used?
I just finished Course.State.hs. Â I came up with:
  isHappy :: Integer -> Bool
  isHappy x = contains 1 $ eval (findM ih (produce sumOfSquares x)) S.empty
  ih :: Integer -> State (S.Set Integer) Bool
  ih x = (\s -> (const $ pure (S.member x s)) =<< put (S.insert x s)) =<< get
  sumOfSquares :: Integer -> Integer
  sumOfSquares = sumOfSquares' 0 . show
   where
    sumOfSquares' acc [] = P.toInteger acc
    sumOfSquares' acc (x:xs) = sumOfSquares' (((P.^) (C.digitToInt x) 2) + acc) xs
which is a LONG way from your point-free solution:
  isHappyC :: Integer -> Bool
  isHappyC = contains 1 . (`eval` S.empty) .
          findM (\j -> State $ \s -> (j == 1 || S.member j s, S.insert j s)) .
            produce (P.sum . (<$>) (join (*) . toInteger . digitToInt) . show)
Is a typically student generally able to come up with something like yours?
All I had to go on was what I had seen earlier in the file. Â It would have taken me years (well, a long time) to figure out yours!
Thanks for a great course!