This is a simple tutorial that doesn't go deep into nix.
Use mkdir to create a new folder and cabal init to initialize a new cabal project.
mkdir project
cd project
cabal init
First download your file that includes the stanzas for default extensions and GHC options. Here is an example:
wget raw.githubusercontent.com/DarinM223/configs/master/defaults.cabal
Open your project.cabal
file and copy the stanzas into it (before the executable section).
Then move cabal-version
to the top of the file, change the version to 2.2
and change the license to 2.2 style (BSD3 becomes BSD-3-Clause, etc).
Then in the executable project
section, add import: exts, opts
where exts
and opts
are stanzas for the extensions and GHC options.
Finally, delete the file you downloaded (so it doesn't conflict with your project.cabal
).
In order to consistently use a modern GHC and GHCJS, we use reflex platform which uses nix to keep the environment reproducible.
We have to add reflex platform as a git submodule to make it possible to run ./try-reflex
from any clone of this repo.
git init
git submodule add https://github.com/reflex-frp/reflex-platform
Ghcid and Ghci require you to be in the reflex platform shell, but your editor most likely won't look good inside the reflex shell. In order to handle this we need tmux to split the terminal into panes. Then the Ghcid and Ghci panes can be inside the shell, and the editor can be in the normal environment.
First run tmux with tmux
in your folder.
- To split vertically, do
C-b "
- To change the vertical pane size, do
C-b M-Up/Down
- To split horizontally, do
C-b %
- To switch to next pane, do
C-b o
- To switch to previous pane, do
C-b ;
You want at least three panes total.
Inside two panes, run ./reflex-platform/try-reflex
to get into the reflex shell first.
Then run cabal new-repl
in one pane and ghcid -c cabal new-repl
in the other. If you have the editor
in another pane, whenever you save a Haskell file, the Ghcid pane should update and show errors if they exist.
Building the JS part takes a while, and it may be inefficient to have it run every time you save a file. However, it would be nice to have an easy way to build the project in GHCJS from the panes we already have. We can do this by running the command to build in GHCJS from Ghci.
The actual command to build in GHCJS is this:
cabal new-build --ghcjs
So we want to run this inside Ghci.
First we have to add the process
library to our build-depends
in project.cabal
(and reload Ghcid after). Then
we add the following after the module
declaration in our main file:
import System.Process
buildJS :: IO String
buildJS = readProcess "cabal" ["new-build", "--ghcjs"] ""
Now reload the Ghci and now you can build to JS in the repl by typing buildJS
.
Now to see what we compiled, we go into the
./dist-newstyle/build/{platform}/ghcjs-{version}/{project}-{project-version}/x/{project}/build/{project}/{project}.jsexe/
path and there should be a index.html
file inside there. If you double click it the browser should open the result in a new tab.