Hello World

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

GHCUP TUI

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!

Intellisense

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…