Learning Haskell #2 - Hello Haskell

The Goal
Like learning many other programming language, I start the first step of writing a tiny hello world program in order to get familiar with the Haskell tooling including:
- What tooling is it?
- Install the tooling.
- Set up the IDE/Editor etc. (I am comfortable with Intellisense somehow)
- Initialize -> Write code -> Compile -> Run
- A little bit dive into the hello world program using my experiences in other programming languages as comparison.
That’s it. I do not expect these will be wordy.
The Tooling
Like I wrote in the previous blog, I got to know the ghcup, which is the modern tooling to install other necessary tooling to kick started in one-stop-shop manner. Similar things in other programming languages like rustup in Rust, volta in nodejs and more.
First of all, you must be comfortable to be a terminal user and you can have a cozy terminal environment like a sophisticated shell - I mean bash, so that I always encourage programming beginner to use UNIX OS (Linux or MACOSX) rather than Windows (Yes, I know, you will still be stick with Windows anyway). Okay, all my following operations are done on with Linux Mint(an Ubuntu distro)/Bash.
To install ghcup, that is pretty easy by one curl command from a remote script and pipe to the sh (yes, bash can interpret sh script), then wait for the installation finish.
Then export ghcup binaries in to your $PATH
variable in .bashrc
etc.
PATH="$HOME/.ghcup/bin:$PATH"
export PATH
Then type ghcup
in your terminal then you should see the output, which means the ghcup installation succeeds. Go to next step.
Installing Other Toolings from ghcup
ghcup is a tool for you to download and install other Haskell related tools from one place instead of you head around internet to find them. In your terminal, run ghcup tui
that displays a wonderful TUI (terminal user interface) for you to pick up tools and their right versions to install or set or uninstall in one place. We shall need these tools
- ghc : Haskell compiler. Yes, Haskell is a compile language
- calbal : Build and package tool
- stack : Yet another build and package tool. I don’t want to dive deeper where it is normal that there are maven and gradle in java world
- hls : Haskell language server. There is a LSP standardizes for different programming languages that allows editor people to create plugin for particular language with abilities like intellisense. VSCode Haskell Extension uses hls under the hood.
ghcup manages all these hassles up. I install and set the recommended ones

Hello Haskell
Create a folder called hello-haskell
and run the ghc init
under the folder. The command has a nice wizard to guide you to setup the project files. It’s straightforward so I won’t go detailed for it. Notably, these files are worthy to mention:
- app/Main.hs : The main entry point for the program like many other programming languages. Well it’s standard. Need to note that ghc init has provided the choice to create Main.hs or Main.lhs. I am curious that what are their differences.
I got this explanation from Copilot…
.hs (Haskell Source): Standard Haskell source code file. Written in plain Haskell syntax. Used for regular Haskell programming.
.lhs (Literate Haskell Source): Literate Haskell allows you to write Haskell code interspersed with documentation in a format similar to Markdown or LaTeX. By default, everything in a .lhs file is treated as a comment unless it is prefixed with > (or other > specific markers, depending on the tool). Commonly used for tutorials, papers, or documentation where code and explanation are mixed.
Simply put, .lhs is something equivalent of Jupiter Notebook in Python world but in Haskell.
- hello-haskell.cabal : Obviously it’s the project definition file for build and for dependencies and many things if you have experiences in other languages. They are
pom.xml
in Java/Maven,package.json
in nodejs,mod
file in Golang,Cargo.toml
in Rust. I will defer the details of this file later.
Build and Run
VSCode’s Haskell extension is fully aware of your local installed ghcup. It detects ghcup and confirms required tools are installed or not, which is handy. So you open your haskell project in VSCode then navigate to the Main.hs
, try typing some code. I assure the intellisense works as expected. Nice!

I will intentionally skip to explain the syntax and IO()
but dive into them in later blog as this one is already too long. I try to build and run Haskell simple hello world program. As I know Haskell is a compile language, which is compiling the source code into binary with a garbage collector embedded in the binary. Yes, Haskell approach is very similar to Golang.
Then I run ghc build
and hit the problem message…
/usr/bin/ld.gold: error: cannot find -lgmp
If you don’t know C programming and gcc process, it will freak you out. Actually the issue happens in linking where gcc does preprocessing -> compiling -> linking to build the source code to executable binary. I guess that Haskell source code is compiled to C somehow in the intermediate step, just guess. ld
command is the linker that does the final step to link all required modules into a single binary. Now the error message is saying libgmp is missing in linking.
What is libgmp?
libgmp is the GNU Multiple Precision Arithmetic Library, a library for performing high-precision arithmetic on integers, rational numbers, and floating-point numbers. It is widely used in programming languages and tools that require efficient handling of large numbers or arbitrary-precision arithmetic.
Then I use apt
to install libgmp-dev
. Remember that related to compilation, you do need to install lib with -dev
because it has extra information for compile. Without -dev
is the production one, it is usually smaller by stripping development information but they might not work in compile.
sudo apt install libgmp-dev
Then compile and run the hello world program successfully
09:20:58 |base|cloud@cloud hello-haskell → cabal build
Resolving dependencies...
Build profile: -w ghc-9.6.7 -O1
In order, the following will be built (use -v for more details):
- hello-haskell-0.1.0.0 (exe:hello-haskell) (first run)
Configuring executable 'hello-haskell' for hello-haskell-0.1.0.0...
Preprocessing executable 'hello-haskell' for hello-haskell-0.1.0.0...
Building executable 'hello-haskell' for hello-haskell-0.1.0.0...
[1 of 1] Compiling Main ( app/Main.hs, /home/cloud/src/hello-haskell/dist-newstyle/build/x86_64-linux/ghc-9.6.7/hello-haskell-0.1.0.0/x/hello-haskell/build/hello-haskell/hello-haskell-tmp/Main.o )
[2 of 2] Linking /home/cloud/src/hello-haskell/dist-newstyle/build/x86_64-linux/ghc-9.6.7/hello-haskell-0.1.0.0/x/hello-haskell/build/hello-haskell/hello-haskell
09:21:04 |base|cloud@cloud hello-haskell → cabal run
Hello, Haskell!
This is another line.
Summary
- I have done the ghcup installation and install ghc, cabal, stack, hls via ghcup
- Install Haskell VSCode extension
- The fundamental workflow of
cabal init
,cabal build
,cabal run
Next blog I will dissect the hello world application and explain some of the language construct in the program. Happy programming…