Hello World in Haskell: The easy way
New package management tool Stack
Recently FPComplete released a new package management tool called stack. This makes getting up and running with Haskell development a hell of a lot nicer than it was previously with cabal alone. Cabal is so hairy that there is a well know term "cabal hell" used to describe some of the common problems that it can cause.
Haskell is a pretty amazing language that has a lot of good ideas and I think it should be used a lot more in the industry. One of the things that has been holding it back from wider adoption has been the confusing and frustrating state of the main package management tool cabal. Stack is looking like a very nice solution to that problem and I hope a lot more people start experimenting with Haskell now.
How to get up and running as a newbie (on osx/linux)
Daniel Mlot recently wrote an article explaining a nice workflow with stack: casual hacking with stack. It can be a bit strange to get set up with Haskell at first so I thought I would put together a few simple steps for Haskell beginners.
Follow the instructions for installing stack on your platform. This should be nice and easy for OSX/linux. (I haven't set up Haskell on windows yet so I'm not sure how well supported it is there.)
You should now have the stack binary on your $PATH somewhere (most likely in ~/bin/).
$ stack --version Version 0.1.2.1, Git revision 09a9fa46fd1d8174ececf4a53774a05b36641457
Note: You may have a different version but that's ok.
Create a new project
Now you are ready to make a new haskell project!
$ mkdir hello-haskell $ cd hello-haskell/ $ stack new Writing: LICENSE Writing: Setup.hs Writing: app/Main.hs Writing: hello-haskell.cabal Writing: src/Lib.hs Writing: test/Spec.hs Writing default config file to: /Users/aaron/CodeBases/hello-haskell/stack.yaml Basing on cabal files: - /Users/aaron/CodeBases/hello-haskell/hello-haskell.cabal Checking against build plan lts-2.17 Selected resolver: lts-2.17 Wrote project config to: /Users/aaron/CodeBases/hello-haskell/stack.yaml
We make a new directory hello-haskell and then run
stack new within it. Stack creates a template project named after the directory.
$ ls -R LICENSE Setup.hs app hello-haskell.cabal src stack.yaml test ./app: Main.hs ./src: Lib.hs ./test: Spec.hs
Let's build and run the new project:
$ stack build hello-haskell-0.1.0.0: configure Configuring hello-haskell-0.1.0.0... hello-haskell-0.1.0.0: build Building hello-haskell-0.1.0.0... Preprocessing library hello-haskell-0.1.0.0... [1 of 1] Compiling Lib ( src/Lib.hs, .stack-work/dist/x86_64-osx/Cabal-184.108.40.206/build/Lib.o ) In-place registering hello-haskell-0.1.0.0... Preprocessing executable 'hello-haskell-exe' for hello-haskell-0.1.0.0... [1 of 1] Compiling Main ( app/Main.hs, .stack-work/dist/x86_64-osx/Cabal-220.127.116.11/build/hello-haskell-exe/hello-haskell-exe-tmp/Main.o ) Linking .stack-work/dist/x86_64-osx/Cabal-18.104.22.168/build/hello-haskell-exe/hello-haskell-exe ... hello-haskell-0.1.0.0: install Installing library in /Users/aaron/CodeBases/hello-haskell/.stack-work/install/x86_64-osx/lts-2.17/7.8.4/lib/x86_64-osx-ghc-7.8.4/hello-haskell-0.1.0.0 Installing executable(s) in /Users/aaron/CodeBases/hello-haskell/.stack-work/install/x86_64-osx/lts-2.17/7.8.4/bin Registering hello-haskell-0.1.0.0... $ stack exec hello-haskell-exe someFunc
So the template app is built and prints out "someFunc" when you run it. Let's change that. Open up app/Main.hs in your favourite editor (Vim and Emacs seem to be the most popular for Haskell development currently).
This is what it looks like currently:
module Main where import Lib main :: IO () main = someFunc
Change the main function to this:
main = do putStrLn "hello world!"
Now build and run it again:
$ stack build $ stack exec hello-haskell-exe hello world!
If you want to add a library from the list of stackage packages all you need to do is add it to the
build-depends section of the
The list of available packages is here: https://www.stackage.org/lts-2.19
... executable hello-haskell-exe hs-source-dirs: app main-is: Main.hs ghc-options: -threaded -rtsopts -with-rtsopts=-N build-depends: base , hello-haskell default-language: Haskell2010 ...
For example let's display some cpu information. Modify the
build-depends section to look like this:
... build-depends: base , cpu , hello-haskell ...
Save the file and run
stack build again. Stack will download the package and install it ready to use.
We can now use the cpu package in the Main.hs file. Alternatively we can also open up the ghci repl and import the cpu package.
$ stack ghci Configuring GHCi with the following packages: hello-haskell GHCi, version 7.8.4: http://www.haskell.org/ghc/ :? for help Loading package ghc-prim ... linking ... done. Loading package integer-gmp ... linking ... done. Loading package base ... linking ... done. Loading package cpu-0.1.2 ... linking ... done. [1 of 1] Compiling Lib ( /Users/aaron/CodeBases/hello-haskell/src/Lib.hs, interpreted ) Ok, modules loaded: Lib. λ: import System.Arch λ: getSystemArch X86_64
The ghci repl can be quite handy for quick testing cycles while you're working on a project. Let's add a simple function to the Main module and reload the code into the ghci repl without having to restart ghci:
module Main where import Lib import System.Arch main :: IO () main = do putStrLn "hello world!" showSystemArch = "The cpu architecture is: " ++ (show getSystemArch)
Now back in ghci we can run
:reload to recompile and then have access to our new function:
λ: :reload Ok, modules loaded: Lib. λ: :l Main [1 of 2] Compiling Lib ( /Users/aaron/CodeBases/hello-haskell/src/Lib.hs, interpreted ) [2 of 2] Compiling Main ( /Users/aaron/CodeBases/hello-haskell/app/Main.hs, interpreted ) Ok, modules loaded: Lib, Main. λ: showSystemArch "The cpu architecture is: X86_64"
You now should have the basic tools set up to start hacking on Haskell projects easily. There's a lot of great free resources for learning Haskell, some good ones are:
Once you have the basics down Ollie Charles' blog has a great exploration of some of the more popular Haskell libraries currently in use: