Panic on parsing embedded files

I have several CSV files that I’m embedding in my program that’s necessary to run properly. This is all just fine, but in the case that I have a typo or error in one of them, I’d like the program to fail immediately when run. To do this currently, I find myself writing a whole lot of code that looks like this:

dataCsv = $(embedStringFile "res/data.csv")

data = case decodeByName dataCsv of
  Left err -> error err
  Right (_, rows) -> rows

I’m just curious if there’s a more “standard” way of handling this people do?

Edit: if there’s a way to do all this at compile-time that would be awesome!

1 Like

You’re using template haskell to embed the file. So move the parsing into the template haskell phase as well!

Remember to use abstraction:

tryDecodingByName err dataCsv =
  case decodeByName dataCsv of
    Left err -> error err
    Right (_, rows) -> rows

dataCsv = $(embedStringFile "res/data.csv")

info = tryDecodingByName "cannot read res/data.csv" dataCsv

You could then lift tryDecodingByName into Template Haskell with a suitable definition:

dataCsv = $(liftM (viaQ (tryDecodingByName "cannot read res/data.csv"))
                  (embedStringFile "res/data.csv"))

…where viaQ (or a similar definition) deals with the changing of data into and from Q Exp values.

1 Like

I put together a simple gist of the idiomatic way to combine embedding the file an parsing during the compile stage.

2 Likes

Thank you all for great examples!