Learning Outcomes

  • Install Haskell via GHCup and Stack

Install GHCup

We will use GHCup to install and manage our tooling. The commands we will use to install GHCup differ slightly from the official installation instructions in order to speed up the installation process.1

Windows

Run this command in a PowerShell session:

Set-ExecutionPolicy Bypass -Scope Process -Force;[System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072; try { & ([ScriptBlock]::Create((Invoke-WebRequest https://www.haskell.org/ghcup/sh/bootstrap-haskell.ps1 -UseBasicParsing))) -Interactive -DisableCurl -Minimal } catch { Write-Error $_ }

In the installation process, select the following options (you might not be asked the first question if you do not have Chocolatey):

Chocolatey was detected on your system...
Continue with GHCup installation?
[C] Continue  [A] Abort  [?] Help (default is "C"): C

Where to install to (this should be a short Path, preferably a Drive like 'C:\')?
If you accept this path, binaries will be installed into 'C:\ghcup\bin' and msys2 into 'C:\ghcup\msys64'.
Press enter to accept the default [C:\]: (Enter)

Specify Cabal directory (this is where haskell packages end up)
Press enter to accept the default [C:\\cabal]: (Enter)

Do you want to install the haskell-language-server (HLS) for development purposes as
well?
[Y] Yes  [N] No  [A] Abort  [?] Help (default is "N"): N

Do you want to install stack as well?
[Y] Yes  [N] No  [A] Abort  [?] Help (default is "N"): N

Do you want to create convenience desktop shortcuts (e.g. for uninstallation and mysys2 shell)?
[Y] Yes  [N] No  [A] Abort  [?] Help (default is "Y"): N

Do you want GHCup to install a default MSys2 toolchain (recommended)?
[Y] Yes  [N] No  [?] Help (default is "Y"): Y

Run

ghcup --version

to check that the installation has succeeded. You might need to restart your terminal first.

Non-Windows

If you are on macOS and have Homebrew, you can install GHCup via Homebrew: brew install ghcup

If not, run this command in a terminal:

export BOOTSTRAP_HASKELL_MINIMAL=1 && curl --proto '=https' --tlsv1.2 -sSf https://get-ghcup.haskell.org | sh

In the installation process, select the following options:

Do you want ghcup to automatically add the required PATH variable to "..."?

[P] Yes, prepend  [A] Yes, append  [N] No  [?] Help (default is "P").

A

Run

ghcup --version

to check that the installation has succeeded. You might need to restart your terminal first.

Install tools using GHCup

We will be installing the following tools:

  • Stack: 3.7.1
  • HLS: 2.11.0.0

To do this, run

ghcup install --set stack 3.7.1
ghcup install --set hls 2.11.0.0

Alternatively, GHCup comes with a convenient TUI (terminal user interfaceA TypeScript construct that defines the shape of an object, specifying the types of its properties and methods. ):

ghcup tui

Follow the instructions of the TUI to install (i) Stack and HLS and set (s) their versions to 3.7.1 and 2.11.0.0 respectively. Once this is done, you should see something like

┌──────────────────────────────────GHCup──────────────────────────────────┐
│    Tool  Version         Tags                          Notes            │
│─────────────────────────────────────────────────────────────────────────│
│✔✔  GHCup 0.1.50.2    latest,recommended                                 │
│─────────────────────────────────────────────────────────────────────────│
│✔✔  Stack 3.7.1       latest                                             │
│✗   Stack 3.5.1                                                          │
│✗   Stack 3.3.1       recommended                                        │
│✗   Stack 3.1.1                                                          │
│✗   Stack 2.15.7                                                         │
│─────────────────────────────────────────────────────────────────────────│
│✔✔  HLS   2.11.0.0    latest                                             │
│✗   HLS   2.10.0.0    recommended                                        │
│✗   HLS   2.9.0.1                                                        │
│✗   HLS   2.9.0.0                                                        │
│✗   HLS   2.8.0.0                                                        │
│✗   HLS   2.7.0.0                                                        │
│✗   HLS   2.6.0.0                                                        │
│─────────────────────────────────────────────────────────────────────────│

If you only see 1 tick instead of 2 ticks ✔✔, that means you have installed the tool but it is not set as your current/active version of that tool. To fix this, select the version and press s to set it.

Check installation

Open the Haskell code bundle and run the following:

stack setup

This normally takes a long time as Stack has to install GHC (the Haskell compiler). This command only needs to be run once in this unit: there’s no need to re-run it for each week’s applied exercises.

Once this is done, you can run the following to verify everything is installed correctly:

stack ghc -- --version

which should output

The Glorious Glasgow Haskell Compilation System, version 9.8.4

This may download any missing dependencies.

VS Code Setup

Install the Haskell extension. This provides Haskell language support including language server, syntaxThe set of rules that defines the combinations of symbols that are considered to be correctly structured statements or expressions in a computer language. highlighting, and linting.

Optional Extras

These may take a while to install, so if you’re installing Haskell during your applied class, it is worth getting started on your applied session work instead.

  • Formatter: Fourmolu
    • Install with stack install fourmolu
    • Set the ‘Haskell: Formatting Provider’ (haskell.formattingProvider) setting in VS Code to ‘fourmolu’
  • Linter: hlint
    • Install with stack install hlint
    • Ensure the ‘Haskell › Plugin › Hlint: Diagnostics On’ (haskell.plugin.hlint.diagnosticsOn) setting in VS Code is enabled, which should be the default

Troubleshooting

Windows Issues

invalid argument (invalid character)

If you get an error like this:

Error: [S-7282]
       Stack failed to execute the build plan.

       While executing the build plan, Stack encountered the following errors:

       <stderr>: commitAndReleaseBuffer: invalid argument (invalid character)

Go to Settings → Time and Language → Language and Region → Administrative language Settings → Change System Locale… → and check ‘Use Unicode UTF-8’. You might need to restart your computer.

Spaces or special characters in username

If you get an error that looks like this:

Warning: [S-8432]
          Stack's 'programs' path is C:\Users\Your Name\AppData\Local\Programs\stack\. It contains a space character. This will prevent building with GHC 9.4.1 or later.

          To avoid sucn problems, use the local-programs-path non-project specific configuration option to specify an alternative path without those characteristics.

or if it says

It contains at least one non-ISO/IEC 8859-1 (Latin-1) character (Unicode code point > 255). This will cause problems with packages that build using the hsc2hs tool with its default template template-hsc.h.

you need to change the local-programs-path Stack configuration option. To do this, edit %AppData%\stack\config.yaml (by default it will be something like C:\Users\Your Name\AppData\Roaming\stack\config.yaml). You can also do this by running the command

notepad.exe $(stack path --global-config)

Add the following line to the bottom of the file:

local-programs-path: C:\stack-programs

macOS Issues

If you get an error that looks something like fatal error: 'ffi.h', it may be because you do not have the Xcode command line tools installed. (These are a collection of command line utilities and other developer tools that many programs rely on.) You can install them by running the following command in your terminal:

xcode-select --install

If you have an existing (possibly broken) installation, you might need to get rid of it first:

sudo rm -rf /Library/Developer/CommandLineTools

Appendix: What are all these different tools?

If you are curious, here’s an explanation of the different Haskell build tools you may come across or hear about. (You do not need to know this.)

  • GHC: Glasgow Haskell Compiler, the most popular Haskell compiler.
  • Cabal: a Haskell build tool that uses GHC to build Haskell packages, which are specified by a .cabal file.
  • Stack: another Haskell build tool that wraps around Cabal. Configuration for Stack is in the stack.yaml file.
    • Stack provides package sets—a collection of packages that compile together—to make managing dependencies less troublesome. The package set is specified by the resolver key in stack.yaml. For example, if your program depends on package A v1 and package B v1, but package A v1 depends on package B v2, your code won’t compile. A Stack package set might specify to use v2 of package A (which depends on package B v2) and v2 of package B v2, which work together. This way, you only need to say ‘I want package A and package B’, and Stack takes care of the rest.
    • Importantly, a package set also relies on a specific version of GHC. In this unit, we have set it up so that Stack manages this for you and installs the correct version of GHC for you.
    • Because .cabal files can be tedious to write by hand, Stack supports an alternative format, hpack, in a package.yaml file. When you run a Stack command, Stack will automatically generate a .cabal file from this.
  • HLS: Haskell Language Server. This is the program that editors (e.g. the VS Code Haskell extension) need to give you nice IDE features. Different versions of HLS work with different versions of GHC, which are indicated by hls-powered in ghcup tui.
    • You might have noticed a hie.yaml file in the applied code bundles. This is hie-bios, a way to tell editors information about the workspace so that the language server works.
  • GHCup: a tool that helps you install specific versions of GHC, Cabal, Stack, and HLS.

You may have noticed these instructions do not get you to install GHC directly via GHCup. This is because as mentioned above, we have set it up so that Stack installs the correct version of GHC for you. This means that if you want to run GHCi for example, you need to run stack ghci instead of just ghci.

(It is possible to install GHC globally so you can run ghci without having to put stack in front of it; however, by default, this will mean you have two copies of GHC installed on your machine! This is why we modified the GHCup installation process slightly from the official instructions so that it doesn’t automatically install GHC and other tools we don’t need. There is a way around this by setting system-ghc: true in Stack, but you must ensure that the version of GHC you have installed matches the Stack package set for your project.)

  1. The only difference from the official installation script is that we stop GHCup from installing GHC (by adding the -Minimal flag to the Windows install script or by setting the environment variable BOOTSTRAP_HASKELL_MINIMAL=1 on Unix), which can take a long time. Instead, we will install GHC via Stack, which will ensure we always have the correct version of GHC needed.