include-file- Inclusion of files in executables at compile-time.

Safe HaskellNone




Inclusion of files in source code via Template Haskell.

When distributing executables, sometimes it is required to attach some other resources in files. Using includeFileInSource you avoid this problem by including those files inside the executable at compile time.


A quick example. I want to include a small image (foo.png) in the executable. I would do:

{-# LANGUAGE TemplateHaskell #-}

import Development.IncludeFile

$(includeFileInSource "foo.png" "myImage")

This defines the myImage value with type ByteString and with the content of the file foo.png.

Using includeFileInSource

The following entities must be in scope when calling includeFileInSource:

  • A ByteString type.
  • A Word8 type, instance of the Num class (at least with the fromInteger method implemented).
  • A pack :: [Word8] -> ByteString function.

This module re-export these for convenience, but you can use your own types (for example, using lazy bytestrings instead of strict bytestrings).

Using lazy bytestrings

To use lazy bytestrings, instead of importing this full module, import it like this:

import Data.ByteString.Lazy (ByteString,pack)
import Development.IncludeFile (includeFileInSource,Word8)

Needless to say, if you have already imported any of those entities, you don't have to do it again.

Performance impact

Benchmarks confirm that it is much faster to use an included bytestring than reading it from a file.

benchmarking include-file
time                 1.814 ns   (1.799 ns .. 1.826 ns)
                     1.000 R²   (0.999 R² .. 1.000 R²)
mean                 1.808 ns   (1.797 ns .. 1.819 ns)
std dev              37.48 ps   (31.27 ps .. 46.78 ps)

benchmarking read-file
time                 4.869 μs   (4.798 μs .. 4.938 μs)
                     0.998 R²   (0.998 R² .. 0.999 R²)
mean                 4.911 μs   (4.857 μs .. 4.968 μs)
std dev              178.8 ns   (150.1 ns .. 212.5 ns)

Large files

Do not use includeFileInSource with large files. The limit between what is and what is not a large file remains uncertain.


Including files

includeFileInSource Source


:: FilePath

Path to file

-> String

Haskell value name

-> Q [Dec] 

Define a value of type ByteString (where ByteString is whatever ByteString type is in scope) with the content of a file.

Convenient re-exports

data ByteString :: *

A space-efficient representation of a Word8 vector, supporting many efficient operations.

A ByteString contains 8-bit bytes, or by using the operations from Data.ByteString.Char8 it can be interpreted as containing 8-bit characters.

data Word8 :: *

8-bit unsigned integer type

pack :: [Word8] -> ByteString

O(n) Convert a '[Word8]' into a ByteString.

For applications with large numbers of string literals, pack can be a bottleneck. In such cases, consider using packAddress (GHC only).