3 ms·
flatten :: ByteString -> [ (String, Int, Int, String) ] flatten json = case decode json of Nothing -> [] -- Type inference here can infer that
by andolanra 10y ago
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.
- jeletonskelly 10y agoOne thing true of all bugs, it passed the type checker.