.. _environment_setup: Setting up your Haskell development environment =============================================== Pre-requisities --------------- Use Linux or Mac. Do not waste time with Haskell on Windows - you may be able to make some progress initially, but you **will** run into weird errors later while bulding certain packages, or while building binaries. **You have been warned.** Make sure you have a **lot of RAM and an SSD.** Serious Haskell projects (not textbook problems) are memory-guzzlers during development & compilation. Plus, if you're like me, you will have 50 browser tabs open, as well. So, it won't be long before your system starts swapping, which is why it's better to have an SSD along with a lot of RAM. For serious Haskell development, we recommend **at least 10 GB of RAM** and **at least 256 GB SSD.** For text-book practice, you can probably get away with 4GB of RAM and an HDD. .. attention:: **Call for contribution** - Screen-recording of installing Stack & Spacemacs + Intero along with the first GHCi session - Screen-recording of installing Stack & VSCode + HIE along with the first GHCi session Installing Haskell ------------------ There are currently **four** ways to install Haskell! Yes, I know that's crazy. Here's what they are: - Via your OS' native package manager, i.e. ``apt-get``, or ``homebrew``, or ``yum`` - Via a `minimal installer `_ or the `Haskell Platform `_ - Via `Stack `_ *(recommended)* - Via Nix/NixOS .. important:: Recommendation Out of the four methods listed above, only Stack is recommended for maintaining your sanity. So, head over to `Stack's Get Started `_ page and follow **only the first step, titled "Download Haskell Stack"** for your OS. The other steps given on that page are covered in greater detail below. Quick primer on Stack --------------------- ``stack`` solves the following problems: - Having different versions of the Haskell compiler (i.e. ``ghc``) available on your machine without messing things up, and using the right ``ghc`` version for your project. - Taking care of which Haskell libraries are known to compile/build with which version of ``ghc``. - Taking care of the dependency graph of libraries, so that all the libraries that your project depends on, compile successfully without you having to manually specify the version of each library. Basically ``stack`` saves you from the *dependency hell* problem. In a sense stack is similar to the following tools from other ecosystems, which attempt to solve some, or all, of the same problems (but they may have solved them in a different manner): - ``rvm`` and ``bundler`` from the Ruby world - ``virtualenv`` from the Python world - ``gvm`` from the Go world - ``nvm`` or ``yarn`` from the NodeJS world Installing an editor -------------------- If you are used to tools like Eclipse/IntelliJ from the Java world, or Visual Studio from the Microsoft world, you are in for a rude shock when it comes to IDEs in Haskell. Firstly, there is no industrial-grade **[I]ntegrated** [D]evelopment [E]nvironment for Haskell - so you can stop looking for it. Secondly, as of Dec 2017, various Haskell editor *plugins*, don't work as well as they should. But, don't worry - all is not lost - you won't have to resort to writing Haskell in ``ed`` or ``nano``. There is stuff available - just lower your expectations. Here are two options that are known to work well: - `Spacemacs `_ with `intero `_ - If you are comfortable with the Emacs editor, this should be your preferred choice. - `VS Code `_ with `HIE: Haskell IDE Engine `_ - If you are comfortable with editors like Sublime, Atom, or VSCode itself, this should be your preferred choice. **Please follow the instructions at** :ref:`hie_installation` .. _hie_installation: Installing VSCode & HIE ^^^^^^^^^^^^^^^^^^^^^^^ .. note:: If you choose to use VSCode + HIE here are the installation instructions. You may skip this sub-section if you plan on using any other editor. Please comment/annotate if these instructions do not work for you. - Install the VSCode editor by downloading it from `here `_ - Install the ``hie`` binary (command-line tool) using the following steps (the last step ``stack install`` is going to take a lot of time - be patient). .. code-block:: shell $ git clone https://github.com/haskell/haskell-ide-engine $ cd haskell-ide-engine $ stack install - Ensure that the ``hie`` binary (command-line tool) has installed successfully by going through the following steps. **Ensure** that you see output similar to what is shown above after you run the ``hie`` command. You can exit it by pressing ``Ctr+c`` .. code-block:: shell $ cd ~ $ hie 2017-12-14 10:44:42.963071 [ThreadId 4] - Setting home directory:/Users/saurabhnanda 2017-12-14 10:44:42.964856 [ThreadId 4] - run entered for HIE Version 0.1.0.0, Git revision ab3cb3e62605625128769d8553646cc4f01db6d1 (1129 commits) x86_64 2017-12-14 10:44:42.966338 [ThreadId 4] - Current directory:/Users/saurabhnanda - Open the VSCode editor and go the the "Extensions" tab, also known as the "plugin marketplace" => search for the ``haskell language server`` plugin (the correct plugin is the one authored by ``Alan Zimmerman``) => Click the ``install`` button. .. image:: _static/hie-installation.png - Restart your editor. - Note down the ``resolver`` that HIE is using (instructions given below): .. _hieWarning: .. warning:: **For HIE & VSCode users** Next, open the ``haskell-ide-engine`` directory (the one which you cloned above) and open the ``stack.yaml`` file. There may be multiple files like ``stack-8.2.1.yml`` or ``stack-8.2.2.yaml``. Ignore those extra files. You need the ``stack.yaml`` file. Note down the resolver (very first line of this file). You will need to use this in the next section. [#hieFootnote]_ For example, on my machine, following are the contents of ``stack.yaml`` and the resolver is ``lts-9.14``. **It may be different on your machine!** .. code-block:: yaml resolver: lts-9.14 packages: - . - hie-apply-refact - hie-base - hie-build-plugin - hie-eg-plugin-async - hie-example-plugin2 # # and more lines will follow # .. _ghci_primer: Get used to GHCi before you start --------------------------------- GHCi is the interactive coding environment for Haskell (also known as a REPL). You will be spending a lot of time in it. It comes wth a `complete user-manual `_ that you can refer to when you need to do more advanced stuff, but, for now, here's some basic stuff that you'll need to know. **Setup your first throw-away project:** .. warning:: **For VSCode & HIE users** In the command given below, make sure you use the correct LTS version as mentioned in hieWarning_ .. code-block:: shell $ stack new --resolver=lts-9.14 first-project $ cd first-project $ stack setup The last command ``stack setup`` may take forever, becuase it will probably download the GHC compiler and a bunch of core/base libraries. Also, it's going to take a shitload of disk-space (about 2GB+). Keep some covfefe (or beer) handy. **Create a new file called Throwaway.hs in your project:** Open ``first-project/src/Throwaway.hs`` and make sure it has the following contents: .. code-block:: haskell module Throwaway where addNumbers :: Int addNumbers = 1 + 2 .. important:: Please take care of the case. In Haskell, modules are named with **CamelCase**. The name of the module and the name of the file sould be the same, for example, in this case the module is called ``Throwaway`` and the file is called ``Throwaway.hs`` **Now, fire-up GHCi:** .. code-block:: shell $ stack ghci Main Lib> :l Throwaway Main> addNumbers 3 **Now, make some changes to Throwaway.hs, WITHOUT EXITING GHCi:** .. note:: Do **not** exit GHCi .. code-block:: haskell module Throwaway where addNumbers :: Int addNumbers = 10 + 20 **Next, reload these changes in GHCI:** .. code-block:: shell Main> :r Main> addNumbers 30 That's the most basic development workflow to follow: - **Always** start ``ghci`` with ``stack ghci`` from within your project directory. This will ensure that the correct version of the compiler is used and that your GHCi is aware of the files in your project and the packages that your project depends on. - Load a file in GHCi via ``:l`` - Run a function - Change something in the function - Reload the file via ``:r`` (There is a difference in the behaviour of ``:l`` and ``:r`` that you may read about, if you are interested.) - Re-run the function .. _correct_docs: Make sure you are reading the correct docs ------------------------------------------ You will find yourself referring to API documentation very often. However, **do not** search for the package names on Google and start reading docs from there. You will end-up in a world of pain without even realising it. Google doesn't know which version of the package you're using, and from a first-hand experience, things change *a lot* between versions. So, here's what you should do: - Check which LTS/resolver you are on -- it'll be the very first setting in your project's ``stack.yaml`` file. - Go to the `Stackage homepage `_ and find the listing page for your LTS/resolver. For example, here's the listing for `lts-9.17 `_ - Search for documentation and packages **only from this page** Hackage vs Stackage & Cabal vs Stack ------------------------------------ Strangely, Haskell has two widely used package repositories. Here is how they are conceptually different and why both exist: - `Hackage `_ is the original package repository. This is where authors upload their packages to share them with the world. - `Stackage `_ pulls *specific versions* of *specific packages* from Hackage and divides them into "sets" known as "snapshots". Each snapshot contains only a single version of any package with a guarantee that all the packages in a given snapshot will successfully build when included in a project. That is, you will not get a dependency hell when your project depends on 5 packages from the same Stackage snapshot. (If you go to a snapshot/LTS' listing page you can verify that there is only one version of each package listed there. On the other hand, if you check the same package on Hackage, you will see all versions of the package listed there). - Hackage has way more packages than Stackage, because, not every author adds their package to the Stackage snapshot. This is probably because, every time a new LTS/snapshot is released, package-authors have to do some extra work to maintain the "no dependeny-hell guaranteee". However, most popular/important packages have already been added to Stackage, so you won't be missing any packages till you start doing advanced Haskell stuff. - The command-line tool called ``cabal`` does not know about Stackage and pulls packages directly from Hackage. Also, cabal+Hackage do not give this "no dependency-hell guarantee" that stack+Stackage works very hard to maintain. - The command-line tool called ``stack`` pulls packages from Stackage, *by default*. Having said that, it *can* pull packages from Hackage if a particular package is not available in its snapshot (but this requires a few extra lines of config). Finally, lot of cabal/Hackage lovers hate stack/Stackage and vice-versa. If you are in the mood for some gossip you can search the interwebs and read some flamewars. One hopes, that at some point in the future, the best parts of stack/Stackage and cabal/Hackage can be merged to build a unified, kickass build-tool. Till that day comes, **just use Stack.** .. [#hieFootnote] Strictly speaking, your project and HIE need to be using the same version of **GHC**, not *necessarily* the same LTS. However, for newbies, we recommend simply using the same LTS because it is simpler and is guaranteed to work.