Hacker News new | comments | show | ask | jobs | submit login

    flatten :: ByteString -> [ (String, Int, Int, String) ]
    flatten json = case decode json of
      Nothing -> []
        -- Type inference here can infer that we're using `val` as
        -- :: HashMap String (HashMap String (HashMap String String))
      Just val ->
        let books = ["Genesis", "Exodus" {- ...and so forth -} ]
        in [ (book, chNum, vsNum, verse)
              -- for every book in the list of books...
           | book <- books
               -- find the corresponding map
           , Just bookMap <- [HM.lookup book val]
               -- for every number in the range [1..max] for chapters
           , chNum <- [1..HM.size bookMap]
               -- pull that map out of the submap
           , Just chMap <- [HM.lookup (show chNum) bookMap]
               -- ...and for every number in the range [1..max] for verses
           , vsNum <- [1..HM.size chMap]
               -- ...pull the verse out of the sub-sub map
           , Just verse <- [HM.lookup (show vsNum) chMap]
Okay, this isn't as type-safe or signed-in-triplicate as the supplied Haskell solution, but if we're comparing size-to-size, then this is pretty terse while also avoiding partial functions (the supplied Haskell solution uses read, which can throw an error if we happen to have a non-numeric key in the wrong place) and still working within the restrictions of what was given.

One thing true of all bugs, it passed the type checker.

Guidelines | FAQ | Support | API | Security | Lists | Bookmarklet | Legal | Apply to YC | Contact