Say I have a dictionary.txt
file, I need to read it into a map and use it in my program, how can I make this dictionary.txt file contained in the compiled exe file?
You'll have to come up with your own way to get it into a Map, but http://hackage.haskell.org/package/file-embed will get it into your compiled binary. We use it for embedding templates in some of our web applications.
You can store serialized data types as bytestring literals. Here's an example:
However, the file-embed automates this process, making it easier to do non-trivial embeddings.
All approaches essentially boil down to representing the static data as a bytestring literal,
{-# LANGUAGE OverloadedStrings #-}
import Data.Binary
import qualified Data.Map as M
import qualified Data.ByteString.Char8 as S
import Data.ByteString.Lazy
import Codec.Compression.GZip
--
-- this is a gzip compressed literal bytestring, storing a binary-encoded Data.Map
--
mytable =
"\US\139\b\NUL\NUL\NUL\NUL\NUL\NUL\ETXEN\
\\219\SO\194 \f\197\224\188\196\CAN\227\US\
\\224\171~\NAKc\GS4ce\161`\178\191\215(\176\
\\190\180\167\231\210\n\241\171\203\191\ti\
\\157\217\149\249< \ENQ\214\&9>\202\162\179a\
\\132X\233\ESC=\231\215\164\SYN\157\DC2D\226*\
\\146\174o\t\167\DLE\209\"i_\240\193\129\199<W\
\\250nC\CAN\212\CAN\162J\160\141C\178\133\216;\
\\\@4\144-W\203\209x\205\140\166\RS\163\237]9f\
\\170\143\ACK\163g\223\STX\184\&7\rH\222\FSW\
\\130\&7D\197\NUL\164\&0U\193\186\t\186o\
\\228\180~\NUL\a6\249\137#\SOH\NUL\NUL"
main = print =<< M.lookup "ghc" m
where
-- build the table from the bytestring:
m :: M.Map String (Maybe String)
m = decode . decompress . fromChunks . return $ mytable
You can use a custom Makefile
/Setup.hs
hook and invoke windres
(if you're on Windows) or objcopy
/elfrc
(if you're on Linux) to compile resources to COFF/ELF objects which you can then combine with your Haskell object files to form the final executable. You can then access resources using Haskell FFI like this (not tested):
-- We have an image resource called "_imgdata"
foreign import ccall "&" _imgdata :: CString
-- Size of _imgdata is 405585 bytes.
imgdata :: CStringLen
imgdata = (_imgdata, 405585)
This solution will be more efficient than using file-embed (no CString
-> ByteString
conversions going on), but also more involved.
As an aside, I also ended up needing resource file support during my work on cabal-install, so it will probably be integrated into some future version of Cabal (if I'll implement it).
I would strongly recommend to use Template Haskell here, to load the file and turn it into a Haskell Datatype. It will not only be compiled into the final binary, but also fully optimized.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With