Creating Locally Hosted Haskell Web GUIs With threepenny-gui

Adam Brohl
3 min readMar 5, 2023

--

Threepenny GUI is a library for Haskell that can be used to create basic GUI applications with Haskell that use the web browser; some information about what it is and some examples of applications others have developed can be found here. For specific information about the installation of the program, the Hackage entry is available here.

Creating The Project

To get started, a Haskell project needs to be created first. Here, the project will be called, “haskellGUI.” A ‘simple’ project will suffice:

$ stack new haskellGUI simple

This will create a new project called ‘haskellGUI’ and will be generated in a folder with the same name as the project. Before installing threepenny, the stack.yaml file and haskellGUI.cabal file need to be modified so that it can be installed properly. First, the dependencies for threepenny need to be added. At the time of writing this, I am using threepenny-0.9.4.0. For this specific version, the extra-deps in stack.yaml should be modified to look like the following:

extra-deps:
- threepenny-gui-0.9.4.0
- snap-core-1.0.5.1
- snap-server-1.1.2.1
- readable-0.3.1
- websockets-snap-0.10.3.1
- io-streams-haproxy-1.0.1.0

Once this is done, the .cabal file needs to be modified so that it properly builds threepenny. To do this, the build-depends section of the .cabal file should be modified to look something like the following:

 build-depends: base >= 4.7 && < 5, threepenny-gui

Now, in the same directory as the rest of the project, run the following command to install all dependences:

$ stack install

To make sure that the dependencies were added correctly, the project can be built and run with the two following commands:

$ stack build
$ stack exec haskellGUI

Writing the Code

Now that the project has been properly set up, the code can finally be written. Here, I will use the “Buttons” example from the threepenny GitHub repository with a few modifications.

First, the import Paths at the top appears to cause errors, so I’ve switched it out with import System.Directory instead. (NOTE: If System.Directory is not working, then add directory-1.3.6.2 to the stack.yaml file, and directory to the .cabal file). Doing this causes the getStaticDir on line 15 to not be recognized, which can now be swapped out with getCurrentDirectory due to the introduction of System.Directory.

The next thing that’s causing a problem is the viewSource function at the bottom of the source code. This function corresponds to a link to the file’s source code. In here, samplesURL is not defined. For now, a fix for this is to instead hard code the directory of the source code.

Running the Project

At this point, all of the errors in the code should be fixed now (aside from a few warnings). Like before, the project can be built with the stack build command, and run with stack exec haskellGUI. If the program properly runs, something like the following should be outputted to the terminal:

Listening on http://127.0.0.1:8023

The link specified in the message corresponds to the URL that the webpage is hosted on. To access the webpage, the URL can be used just like any other, and should direct towards something that looks like this:

And to test to make sure it works, pressing the buttons should have the intended behavior. Note: This is a locally hosted webpage, so someone outside of the network it is hosted on will not be able to join. To stop the process, simply go back to the terminal and press CTRL + C.

--

--