diff --git a/docs/install.md b/docs/install.md index ec06aa2..f2c770b 100644 --- a/docs/install.md +++ b/docs/install.md @@ -34,13 +34,11 @@ GHCup has two main channels for every tool: **recommended** and **latest**. By d Also see [tags and shortcuts](../guide/#tags-and-shortcuts) for more information. -## First steps +## Next steps -1. To get started with creating a Haskell project, follow the [Getting Started with Haskell and Cabal](https://cabal.readthedocs.io/en/stable/getting-started.html) guide +1. Follow the [First steps guide](../steps) on how to build a "Hello world" program, use `ghc`, run an interactive REPL and create a Haskell project 2. To understand the difference and overlap of `stack` and `cabal`, read on [here](https://gist.github.com/merijn/8152d561fb8b011f9313c48d876ceb07) -3. To learn Haskell, try any of those: - - A beginner friendly [4-lectures course](https://github.com/haskell-beginners-2022/course-plan) with exercises (by [Kowainik](https://kowainik.github.io/)) - - An in-depth university [CIS 194 Haskell course](https://www.cis.upenn.edu/~cis194/spring13/) including exercises (by [Brent Yorgey](https://byorgey.wordpress.com/)) +3. To learn Haskell proper check out the links at [How to learn Haskell proper](../steps#how-to-learn-haskell-proper) 4. To learn more about Haskell Toolchain management, check out the [ghcup user guide](./guide.md) ## Uninstallation diff --git a/docs/steps.md b/docs/steps.md new file mode 100644 index 0000000..e95718a --- /dev/null +++ b/docs/steps.md @@ -0,0 +1,337 @@ +# First steps + +In this guide we'll take a look at a few core tools that are installed +with the Haskell toolchain, namely, `ghc`, `runghc` and `ghci`. +These tools can be used to compile, interpret or explore Haskell programs. + + +First, let's start by opening your system's command line interface +and running `ghc --version` to make sure we have successfully +installed a Haskell toolchain: + +``` +➜ ghc --version +The Glorious Glasgow Haskell Compilation System, version 8.10.7 +``` + +If this fails, consult [the Getting started page](../install) for information on +how to install Haskell on your computer. + +## Compiling programs with ghc + +Running `ghc` invokes the Glasgow Haskell Compiler (GHC), and can be used to +compile Haskell modules and programs into native executables and libraries. + +Create a new Haskell source file named `hello.hs`, +and write the following code in it: + +```hs +main = putStrLn "Hello, Haskell!" +``` + +Now, we can compile the program by invoking `ghc` with the file name: + +```sh +➜ ghc hello.hs +[1 of 1] Compiling Main ( hello.hs, hello.o ) +Linking hello ... +``` + +For more in-depth information about the files `ghc` produces, +follow the [GHC user guide](https://downloads.haskell.org/ghc/latest/docs/html/users_guide/using.html#getting-started-compiling-programs) guide. + +Now we run our program: + +```sh +➜ ./hello +Hello, Haskell! +``` + +Alternatively, we can skip the compilation phase by using the command `runghc`: + +```sh +➜ runghc hello.hs +Hello, Haskell! +``` + +`runghc` interprets the source file instead of compiling it and does not +create build artifacts. This makes it very useful when developing programs +and can help accelerate the feedback loop. More information about `runghc` +can be found in the +[GHC user guide](https://downloads.haskell.org/ghc/latest/docs/html/users_guide/runghc.html). + +### Turning on warnings + +The `-Wall` flag will enable GHC to emit warnings about our code. + +```sh +➜ ghc -Wall hello.hs -fforce-recomp +[1 of 1] Compiling Main ( hello.hs, hello.o ) + +hello.hs:1:1: warning: [-Wmissing-signatures] + Top-level binding with no type signature: main :: IO () + | +1 | main = putStrLn "Hello, Haskell!" + | ^^^^ +Linking hello ... +``` + +While Haskell can infer +the types of most expressions, it is recommended that top-level definitions +are annotated with their types. + +Now our `hello.hs` source file should looks like this: + +```hs +main :: IO () +main = putStrLn "Hello, world!" +``` + +And now GHC will compile `hello.hs` without warnings. + +## An interactive environment + +GHC provides an interactive environment in a form of a +Read-Evaluate-Print Loop (REPL) called GHCi. +To enter the environment run the program `ghci`. + +```sh +➜ ghci +GHCi, version 9.0.2: https://www.haskell.org/ghc/ :? for help +ghci> +``` + +It provides an interactive prompt where Haskell expressions can be written and +evaluated. + +For example: + +```sh +ghci> 1 + 1 +2 +ghci> putStrLn "Hello, world!" +Hello, world! +``` + +We can define new names: + +```sh +ghci> double x = x + x +ghci> double 2 +4 +``` + +We can write multi-line code by surrounding it with `:{` and `:}`: + +```hs +ghci> :{ +| map f list = +| case list of +| [] -> [] +| x : xs -> f x : map f xs +| :} +ghci> map (+1) [1, 2, 3] +[2,3,4] + +``` + +We can import Haskell source files using the `:load` command (`:l` for short): + +```sh +ghci> :load hello.hs +[1 of 1] Compiling Main ( hello.hs, interpreted ) +Ok, one module loaded. +ghci> main +Hello, Haskell! +``` + +As well as import library modules: + +```sh +ghci> import Data.Bits +ghci> shiftL 32 1 +64 +ghci> clearBit 33 0 +32 +``` + +We can even ask what the type of an expression is using the `:type` command +(`:t` for short): + +```sh +λ> :type putStrLn +putStrLn :: String -> IO () +``` + +To exit `ghci`, use the `:quit` command (or `:q` for short) + +```sh +ghci> :quit +Leaving GHCi. +``` + +A more thorough introduction to GHCi can be found in the +[GHC user guide](https://downloads.haskell.org/~ghc/latest/docs/html/users_guide/ghci.html). + +### Using external packages in ghci + +By default, GHCi can only load and use packages that are +[included with the GHC installation](https://downloads.haskell.org/ghc/latest/docs/html/users_guide/9.2.2-notes.html#included-libraries). + +However, users of the [cabal-install](https://www.haskell.org/cabal) and +[stack](http://haskellstack.org) build tools can download and load external packages +very easily using the following commands: + +cabal-install: + +```sh +cabal repl --build-depends async,say +``` + +Stack: + +```sh +stack exec --package async --package say -- ghci +``` + +And the modules of the relevant packages will be available for import: + +```sh +GHCi, version 9.0.1: https://www.haskell.org/ghc/ :? for help +ghci> import Control.Concurrent.Async +ghci> import Say +ghci> concurrently_ (sayString "Hello") (sayString "World") +Hello +World +``` + +Stack users can also use this feature with `runghc` and `ghc` by replacing +`ghci` in the command above, and cabal-install users can generate an +environment file that will make `async` and `say` visible for GHC tools +in the current directory using this command: + +```sh +cabal install --lib async say --package-env . +``` + +Many more packages are waiting for you on [Hackage](https://hackage.haskell.org). + +## Creating a proper package with modules + +The previous methods to compile Haskell code are for quick experiments and small +programs. Usually in Haskell, we create cabal projects, where build tools such as +`cabal-install` or `stack` will install necessary dependencies and compile modules +in correct order. For simplicity's sake, this section will only use `cabal-install`. + +To get started, run: + +```sh +mkdir haskell-project +cd haskell-project +cabal init --interactive +``` + +If you let it generate a simple project with sensible defaults, then you should have these files: + +* `src/MyLib.hs`: the library module of your project +* `app/Main.hs`: the entry point of your project +* `haskell-project.cabal`: the "cabal" file, describing your project, its dependencies and how it's built + +To build the project, run: + +```sh +cabal build +``` + +To run the main executable, run: + +```sh +➜ cabal run +Hello, Haskell! +someFunc +``` + +Now let's add a dependency and adjust our library module. Open `haskell-project.cabal` +and find the library section: + +``` +library + exposed-modules: MyLib + + -- Modules included in this library but not exported. + -- other-modules: + + -- LANGUAGE extensions used by modules in this package. + -- other-extensions: + build-depends: base ^>=4.14.3.0 + hs-source-dirs: src + default-language: Haskell2010 +``` + +The interesting parts here are `exposed-modules` and `build-depends`. +To add a dependency, it should look like this: + +``` + build-depends: base ^>=4.14.3.0 + , directory +``` + +Now open `src/MyLib.hs` and change it to: + +```hs +module MyLib (someFunc) where + +import System.Directory + +someFunc :: IO () +someFunc = do + contents <- listDirectory "src" + putStrLn (show contents) +``` + +To add a module to your package, adjust `exposed-modules`, like so + +``` + exposed-modules: MyLib + OtherLib +``` + +then create `src/OtherLib.hs` with the following contents: + +```hs +module OtherLib where + +otherFunc :: String -> Int +otherFunc str = length str +``` + +To use this function interactively, we can run: + +```sh +➜ cabal repl +ghci> import OtherLib +ghci> otherFunc "Hello Haskell" +13 +``` + +For further information about how to manage Haskell projects +see the [Cabal user guide](https://cabal.readthedocs.io/en/stable/getting-started.html). + +# Where to go from here + +## How to learn Haskell proper + +To learn Haskell, try any of those: + +- A beginner friendly [4-lectures course](https://github.com/haskell-beginners-2022/course-plan) with exercises (by [Kowainik](https://kowainik.github.io/)) +- An in-depth university [CIS 194 Haskell course](https://www.cis.upenn.edu/~cis194/spring13/) including exercises (by [Brent Yorgey](https://byorgey.wordpress.com/)) + +## Projects to contribute to + +* [https://github.com/haskell/haskell-language-server](https://github.com/haskell/haskell-language-server) +* [https://github.com/haskell/cabal](https://github.com/haskell/cabal) +* [https://github.com/commercialhaskell/stack](https://github.com/commercialhaskell/stack) +* [https://gitlab.haskell.org/haskell/ghcup-hs](https://gitlab.haskell.org/haskell/ghcup-hs) +* [https://github.com/jgm/pandoc](https://github.com/jgm/pandoc) +* [https://github.com/simonmichael/hledger](https://github.com/simonmichael/hledger) +* [https://github.com/koalaman/shellcheck](https://github.com/koalaman/shellcheck) diff --git a/mkdocs.yml b/mkdocs.yml index 0c02bf1..7ac8b4e 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -13,7 +13,8 @@ theme: nav: - Home: index.md - - "Getting Started": install.md + - "Getting started": install.md + - "First steps": steps.md - "User Guide": guide.md - "Developer Guide": dev.md - About: about.md