Haskell/Standalone programs

From Wikibooks, open books for an open world
Jump to navigation Jump to search

Let's build a simple Haskell application, i.e. a piece of standalone software.

The Main module[edit | edit source]

The basic requirement behind this is to have a module Main with an entry point called main and of type IO ().

-- thingamie.hs
module Main where

main = putStrLn "Bonjour, world!"

We already know how to load this into GHCi, but here's how we compile it and then run it independently:

$ ghc --make -o bonjourWorld thingamie.hs
$ ./bonjourWorld
Bonjour, world!

Voilà! You now have a standalone application built in Haskell.

Other modules[edit | edit source]

Most programs grow to be complicated enough to split across different files. Here is a toy example of an application which uses two modules.

-- Hello.hs
module Hello where

hello = "Bonjour, world!"
-- thingamie.hs
module Main where

import Hello

main = putStrLn hello

We can compile this fancy new program in the same way as before. The --make flag tells GHC to automatically detect dependencies in the files you are compiling. That is, since thingamie.hs imports a module Hello, GHC will search the Haskell files in the current directory for files that implement Hello and also compile them. If Hello depends on other modules, GHC will automatically detect those dependencies as well.

$ ghc --make -o bonjourWorld thingamie.hs
$ ./bonjourWorld
Bonjour, world!

You may have noticed that the file with the Main module, thingamie.hs, does not have a name matching the module name, which goes against what we said in the Modules chapter. That is not a problem because the point of having matching module and file names is allowing GHC to find the files automatically. Since that process always begins from Main, whose file we specify in the command line when calling GHC, the file of the Main module need not follow the convention.

If you want to search in other places for source files (including a nested structure of files and directories), you can add the starting point for the dependency search with the -i flag. This flag takes multiple, colon-separated directory names as its argument.

As a contrived example, the following program has three files all stored in a src/ directory. The directory structure looks like:

HaskellProgram/
   src/
      Main.hs
      GUI/
           Interface.hs
      Functions/
           Mathematics.hs

The Main module imports its dependencies by searching a path analogous to the module name — so that import GUI.Interface would search for GUI/Interface (with the appropriate file extension).

To compile this program from within the HaskellProgram directory, invoke GHC with:

$ ghc --make -isrc -o sillyprog Main.hs