Extending file-embed Haskell package

Posted in category haskell on 2013-11-27
Tags: haskell

When developing in Haskell there are generally two ways to build/debug your projects - cabal and/or GHCi. Typically *.cabal file is located in the root of the project, all source files are in src/ folder, plus some other folders as needed. So, you could imagine that configuring, building and installing of a local project with using cabal should happen from the root folder (where *.cabal file is located). In case of GHCi, typically project is compiled from src/ folder, so that hierarchy of namespaces is visible to GHCi itself. Unfortunately, with this approach it might sometimes be problematic to support both ways in case for example when project has some embedded resource files (good example of Haskell package that allows to embed files/folders content into a program is file-embed, created and maintained by Michael Snoyman). file-embed package uses template haskell in order to precompile the content of some files as hardcoded strings in the program. So, with using template haskell and file-embed you could instruct GHC to precompile the content of specified files into the body of your program. And I guess, you feel where the problem already, right? :) Since we are building our solution from two different folders (./ and ./src/) the path to the file might not be the same in order to make embedding working.

Here is an example of how file-embed allows to embed the content of an arbitrary file into the body of your program:

resource :: String
resource = decode $ B.unpack $(embedFile "src/res/file.txt")

Remember, that in case file does not exist, your program will not compile.

So, in order to cope with this issue I introduced another embedOneFileOf function in file-embed package that accepts list of paths out of which first existing path will be used to be embedded as a resource:

resource :: String
resource = decode $ do
  B.unpack $(embedOneFileOf ["src/res/file.txt", "res/file.txt"])

With this approach it should now be possible to satisfy both cabal and GHCi.

Here is a link to the pull request to change file-embed Haskell package.

Thanks to the maintainer, Michael Snoyman, who reviewed the change and released it in no time.