# Set up a Haskell Project with Stack

In what follows we will set up a simple project using `stack` and see how to run code in the project using `ghci`, Haskell’s interactive read-eval-print loop (repl). This program will print a message on the screen. Next, we develop a program prints a random integer to the screen. This will be done using `randomIO` in the `System.Random` module. To use `System.Random`, we must find the package in which it is defined. We’ll do this using Hackage, a search tool for packages. The next steps are

• Reference the package for `System.Random` in `package.yaml`.

• Use `ghci` to test `randomIO`.

• Modify the program so that it prints out a random integer.

• Compile the program, again using stack.

• Run the program from the command line.

In the appendix, we analyze the types used in the program and show how another search tool, `Hoogle`, can be used to find a type signature from a function name or a function name from a type signature.

## Initial setup

We will run `stack new randomStuff` to start a new project named randomStuff. This will set up a project with the file `./app/Main.hs` which looks like this:

``````module Main where

import Lib

main :: IO ()
main = someFunc
``````

If we look at `.src/Lib.h`, we find the below:

``````module Lib ( someFunc ) where

someFunc :: IO ()
someFunc = putStrLn "someFunc"
``````

Thus, running the program `Main.hs` should print “someFunc”. Let’s set things up now:

``````\$ stack new randomStuff
\$ stack ghci
*Main Lib> main
someFunc
``````

Success!

We are going to add code to our program so that it prints out a random number. For this we will use the module `System.Random`. We’ll need to find the name of the package that exposes this module. There are two good ways to do this

• Go to Hackage and type “System.Random” in the search box.

Either way, if look closely at the fine print at the top, we find the text

``````random-1.2.0: Pseudo-random number generation
``````

This is our clue. So we put the line

``````- random
``````

in the file `package.yaml` in just the right place, like so:

``````dependencies:
- base >= 4.7 && < 5
- random -- ((NEW TEXT))
``````

Then we change `Main.hs` so that it looks like this:

``````module Main where

import Lib
import System.Random

main :: IO ()
main = someFunc

newRand = randomIO :: IO Int
``````

Thus, we have imported the module `System.Random` and used it to define `newRand`. Before proceeding further, we test to see if this works:

``````\$ stack ghci

*Main Lib> newRand
1095906040554822953

*Main Lib> newRand
2091178867183333176
``````

Yes! Making progress.

Note. When you change code but are still in `ghci`, you can type `:reload` (or just `:r`) to reload the code.

## Finishing the program

We’ve tested `randomIO`, and it works. But we would like to fully integrate it into our program so that when we run the program, it prints a random number to the screen, with no need use `stack ghci`. Below is one solution.

``````module Main where

import System.Random

main :: IO ()
main = newRand >>= print

newRand = randomIO :: IO Int
``````

While the code will be explained in detail in the appendix, here is a brief version: `newRand` has type `IO Int` and `print` has type `a -> IO ()`, where `a` is “any type.” In the present context, `a = Int`. So we have to fit a thing of type `IO Int` and a thing of type `Int -> IO ()` together to make something of type `IO ()`, which is the type of `main`. That is what the “bind” operator `>>=` does.

Next, we reload `ghci` and run `main`:

``````> :reload
> main
-3910396880313191658
``````

The last step is to compile our program and run it in the terminal:

``````\$ stack build
...

\$ ./app/Main
664397062957259411

\$ ./app/Main
-1747843471900380854
``````

When we ran `stack build`, stack ran `ghc` on `./app/Main.hs` and produced the executable file `./app/Main`, which we ran from the command line to produce a “random” integer.

## Appendix: Discovering the Bind Operator

Let’s try to understand how we might have come to discover the bind operator `>>=` as a way to fit together `newRand`, which makes a random number, and `print`, which transforms values into something that can be printed. To begin, we need the type signature of `print`. To find it, we use Hoogle, a search tool for functions and values. Putting `print` into the Hoogle search box, we get

``````Show a => a -> IO ()
``````

What this means is that `print` has type `a -> IO a`, where `a` is constrained to be of typeclass `Show a`. Things of typeclass `Show a` are printable.

At this point we have a value of type `IO Int` and a function of type `a -> IO ()`, which in our context is of type `Int -> IO ()`. We want to fit these two things together to make e value of type `IO ()`. Suppose we had a magical operator `op` that would do this, so that

``````newRand op print :: IO ()
``````

This is the same as having a function `(op)` such that

``````(op) newRand print :: IO ()
``````

If the expression above has type `IO ()` then `(op)` must have type

``````IO Int -> (Int -> IO ()) -> IO ()
``````

This type signature is an instance of the general pattern

``````m a -> (a -> m ()) -> m ()
``````

where `m = IO` and `a = Int`. And this last type signature is an instance of the still more general

``````m a -> (a -> m b) -> m b
``````

Now that we know the type of the thing we need, we use Hoogle to find it. Typing `m a -> (a -> m b) -> m b` into the Hoogle search box, we find the function `(>>=)`. It is called bind and it is written :

``````(>>=) :: forall a b . Monad m => m a -> (a -> m b) -> m b
``````

The term `Monad` occurs in the typeclass part of the definition. For now it is enough to know that

• There is a bind function whenever `m` is a monad.
• `IO` is a monad
• Therefore there is a bind function `IO a -> (a -> IO b) -> IO b`.

Remember this little syllogism when you encounter monads.

• Hackage — search for libraries, packages

• Hoogle — search for functions and type signatures
{"ft_lang_label":"__label__en","ft_lang_prob":0.7120651,"math_prob":0.80923826,"size":5580,"snap":"2020-34-2020-40","text_gpt3_token_len":1509,"char_repetition_ratio":0.12213056,"word_repetition_ratio":0.07305936,"special_character_ratio":0.27903226,"punctuation_ratio":0.13002567,"nsfw_num_words":0,"has_unicode_error":false,"math_prob_llama3":0.9914592,"pos_list":[0],"im_url_duplicate_count":[null],"WARC_HEADER":"{\"WARC-Type\":\"response\",\"WARC-Date\":\"2020-09-24T04:14:55Z\",\"WARC-Record-ID\":\"<urn:uuid:6a9d709d-91b7-4517-a857-d4bf2478d3ce>\",\"Content-Length\":\"13807\",\"Content-Type\":\"application/http; msgtype=response\",\"WARC-Warcinfo-ID\":\"<urn:uuid:6134becc-11ad-444a-b626-a484717fa2ac>\",\"WARC-Concurrent-To\":\"<urn:uuid:fc6fb7b6-91c7-4f42-85aa-ade987acd0fa>\",\"WARC-IP-Address\":\"206.189.184.194\",\"WARC-Target-URI\":\"https://jxxcarlson.io/posts/2020-09-14-haskell/\",\"WARC-Payload-Digest\":\"sha1:EDDUMBJSF27ORMQFKOMYYGRDDKOQQ7YH\",\"WARC-Block-Digest\":\"sha1:VJIV43VP4VVRMIIBRZDBMHIHIJA35OPX\",\"WARC-Identified-Payload-Type\":\"text/html\",\"warc_filename\":\"/cc_download/warc_2020/CC-MAIN-2020-40/CC-MAIN-2020-40_segments_1600400213454.52_warc_CC-MAIN-20200924034208-20200924064208-00315.warc.gz\"}"}