Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
137 changes: 76 additions & 61 deletions tutorials/01_fp-env.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ Lambda calculus is good to understand (at least basics) when you want to start w
* [Lambda calculus (Stanford)](https://plato.stanford.edu/entries/lambda-calculus/)
* [The Lambda Calculus for Absolute Dummies (like myself)](http://palmstroem.blogspot.cz/2012/05/lambda-calculus-for-absolute-dummies.html)

For FIT CTU students, there are subjects [BI-PPA](https://edux.fit.cvut.cz/courses/BI-PPA) and [MI-PSL](https://edux.fit.cvut.cz/courses/MI-PSL) which also cover basics of lambda calculus and functional programming.
For FIT CTU students, there are subjects [BI-PPA](https://courses.fit.cvut.cz/BI-PPA/) and [MI-PSL](https://courses.fit.cvut.cz/MI-PSL/) which also cover basics of lambda calculus and functional programming.

### Function as first class-object

Expand Down Expand Up @@ -55,7 +55,7 @@ Principles [[jdegoes](https://twitter.com/jdegoes/status/974045822424776704?s=09
* [Cabal] = system for building and packaging.
* [Stack] = managing Haskell projects, works with [Cabal] for you.

:point_right: Please these (or check if installed already) - you can follow instruction on official websites one by one or (better) install [Haskell Platform], which includes all of those and also most common packages.
:point_right: Please, install these (or check if installed already) - you can follow instruction on official websites one by one or (better) install [Haskell Platform], which includes all of those and also most common packages.

### Editors and IDEs

Expand All @@ -72,40 +72,42 @@ Most probably you will need following stuff:
* [hindent] = indenter, pretty print
* [stylish-haskell] = code prettifier ("good style")

Install those with [Cabal] (by default it will install just for you to your profile, ensure that you have `~/.cabal/bin` in your `PATH`. The installation might take a while - it has a lot of dependencies and needs to build them from Haskell source code. If you want to install something with [Cabal] to all users, use `--global` flag.
Install those with [Cabal] (by default it will install just for you to your profile, ensure that you have `~/.cabal/bin` in your `PATH`) or with [Stack]. The installation might take a while - it has a lot of dependencies and needs to build them from Haskell source code. If you want to install something with [Cabal] to all users, use `--global` flag.

```
```console
$ cabal update
$ cabal install hlint stylish-haskell hindent ghc-mod
$ stack install hlint stylish-haskell hindent ghc-mod
```

### Sites for searing

* [Hoogle] = "Google" for Haskell world
* [Hayoo!] = "Yahoo" for Haskell world
* [Hackage] = package archive, there are packages which can you install and use standalone or as modules for your projects (similar to PyPI for Python, RubyGems for Ruby, etc.)
* [Stackage] = package archive, alternative to [Hackage], only stable packages

:point_right: Take a look at them...

### Haskell, JavaScript and new languages

If you like to build (frontend/backend) JavaScript applications you can do that nicely with Haskell. There are multiple options, most known are:
If you like to build (frontend/backend) JavaScript applications you can do that nicely with Haskell or similar language. There are multiple options, most known are:

* [GHCJS]
* [Haste]
* [PureScript]
* [Elm]
* [Elm] (will be covered in later lectures)

This is a nice example of practical usage of Haskell for web projects! It is so much easier (and safer) to write JavaScript in Haskell than just plain JavaScript. Some of those are not just Haskell dialects or libraries but new languages deeply inspired by Haskell. For more information, read about [The JavaScript Problem](https://wiki.haskell.org/The_JavaScript_Problem). We will slightly look at this at the end of this course.

## Try to be interactive

Now you should have [GHC] installed (and others as well, but we won't need an editor for this time), you can test it out with the following command.
Now you should have [GHC] installed from package or via Stack (and others as well, but we won't need an editor for this time), you can test it out with the following command.

```
```console
% ghc --version
The Glorious Glasgow Haskell Compilation System, version 8.0.2
% stack exec -- ghc --version
The Glorious Glasgow Haskell Compilation System, version 8.0.2
```

First, let's try the interactive environment and evaluate some basic expression in Haskell for the first time.
Expand Down Expand Up @@ -244,7 +246,7 @@ Prelude> 5 `mod` 3
2
```

### Giving name to expression
### Giving a name to an expression

In GHCi you can name an expression with `let` and assignment.

Expand Down Expand Up @@ -359,7 +361,7 @@ main = putStrLn "Hello, world!"

Now use `ghc` compiler to compile the file:

```
```console
% ghc 01_hw.hs
[1 of 1] Compiling Main ( 01_hw.hs, 01_hw.o )
Linking 01_hw ...
Expand All @@ -374,7 +376,7 @@ You can see some similar output as when you were loading a file in GHCi just her

And you can run the executable:

```
```console
% ./01_hw
Hello, world!
```
Expand All @@ -399,9 +401,9 @@ main = do
putStrLn (greet name)
```

Now how to make it work together? Do you know `Makefile`s from `C/C++`? Don't worry... GHC is a great tool and does such painful work for you (reads imports and looking up the files - you just need to have good naming of modules/files):
Now how to make it work together? Do you know `Makefile` (for example, from `C/C++`)? Don't worry... GHC is a great tool and does such painful work for you (reads imports and looking up the files - you just need to have a standard naming of modules/files):

```
```console
% ghc --make Main.hs
[1 of 2] Compiling HWLib ( HWLib.hs, HWLib.o )
[2 of 2] Compiling Main ( Main.hs, Main.o )
Expand All @@ -418,37 +420,48 @@ Compiling application made from multiple source codes is not so complicated in t

Let's do the *Hello, world!* app with [Stack]. First, verify that you have it installed.

```
```console
% stack --version
Version 1.4.0, Git revision e714f1dd3fade19496d91bd6a017e435a96a6bcd (4640 commits) x86_64 hpack-0.17.0
Version 1.9.3, Git revision 40cf7b37526b86d1676da82167ea8758a854953b (6211 commits) x86_64 hpack-0.31.1
```

Then you can create a new project with default template:

```
```console
% stack new HelloWorld
Downloading template "new-template" to create project "HelloWorld" in HelloWorld/ ...

...
The following parameters were needed by the template but not provided: author-name
You can provide them in /home/user/.stack/config.yaml, like this:
templates:
params:
author-name: value
Or you can pass each one as parameters like this:
stack new HelloWorld new-template -p "author-name:value"


The following parameters were needed by the template but not provided: author-email, author-name, category, copyright, github-username
You can provide them in /home/user/.stack/config.yaml, like this:
templates:
params:
author-email: value
author-name: value
category: value
copyright: value
github-username: value
Or you can pass each one as parameters like this:
stack new HelloWorld new-template -p "author-email:value" -p "author-name:value" -p "category:value" -p "copyright:value" -p "github-username:value"

Looking for .cabal or package.yaml files to use to init the project.
Using cabal packages:
- HelloWorld/HelloWorld.cabal
- HelloWorld/

Selecting the best among 11 snapshots...
Selecting the best among 15 snapshots...

Downloaded lts-9.11 build plan.
Missing some cabal revision files, updating indices
Selected mirror https://s3.amazonaws.com/hackage.fpcomplete.com/
Downloading timestamp
Downloading snapshot
Updating index
Updated package list downloaded
Populated index cache.
* Matches lts-9.11

Selected resolver: lts-9.11
Initialising configuration using resolver: lts-9.11
* Matches lts-13.8

Selected resolver: lts-13.8
Initialising configuration using resolver: lts-13.8
Total number of user packages considered: 1
Writing configuration to file: HelloWorld/stack.yaml
All done.
Expand Down Expand Up @@ -481,15 +494,15 @@ main = do

Now you don't use GHC directly, but call it via `stack build`:

```
```console
% stack build
No compiler found, expected minor version match with ghc-8.0.2 (x86_64) (based on resolver setting in /home/user/.stack/global-project/stack.yaml).
To install the correct GHC into /home/user/.stack/programs/x86_64-linux/, try running "stack setup" or use the "--install-ghc" flag. To use your system GHC installation, run "stack config set system-ghc --global true", or use the "--system-ghc" flag.
```

As you see `stack` doesn't want to use system-wide installation of `ghc` but local instead by default. Just run `stack setup` so `stack` will prepare local `ghc` (it will take some time) and then try to build.

```
```console
% stack setup
Preparing to install GHC to an isolated location.
This will not interfere with any system-level installation.
Expand All @@ -507,35 +520,38 @@ Using cabal packages:

Selecting the best among 11 snapshots...

* Matches lts-9.11
* Matches lts-13.8

Selected resolver: lts-9.11
Selected resolver: lts-13.8
Initialising configuration using resolver: lts-9.11
Total number of user packages considered: 1
Writing configuration to file: stack.yaml
All done.

% stack build
Linking /home/user/.stack/setup-exe-cache/x86_64-linux/tmp-Cabal-simple_mPHDZzAJ_1.24.2.0_ghc-8.0.2 ...
Building all executables for `HelloWorld' once. After a successful build of all of them, only specified executables will be rebuilt.
HelloWorld-0.1.0.0: configure (lib + exe)
Configuring HelloWorld-0.1.0.0...
HelloWorld-0.1.0.0: build (lib + exe)
Preprocessing library HelloWorld-0.1.0.0...
[1 of 1] Compiling Lib ( src/Lib.hs, .stack-work/dist/x86_64-linux/Cabal-1.24.2.0/build/Lib.o )
Preprocessing executable 'HelloWorld-exe' for HelloWorld-0.1.0.0...
[1 of 1] Compiling Main ( app/Main.hs, .stack-work/dist/x86_64-linux/Cabal-1.24.2.0/build/HelloWorld-exe/HelloWorld-exe-tmp/Main.o )
Linking .stack-work/dist/x86_64-linux/Cabal-1.24.2.0/build/HelloWorld-exe/HelloWorld-exe ...
Preprocessing library for HelloWorld-0.1.0.0..
Building library for HelloWorld-0.1.0.0..
[1 of 2] Compiling Lib ( src/Lib.hs, .stack-work/dist/x86_64-linux-tinfo6/Cabal-2.4.0.1/build/Lib.o )
[2 of 2] Compiling Paths_HelloWorld ( .stack-work/dist/x86_64-linux-tinfo6/Cabal-2.4.0.1/build/autogen/Paths_HelloWorld.hs, .stack-work/dist/x86_64-linux-tinfo6/Cabal-2.4.0.1/build/Paths_HelloWorld.o )
Preprocessing executable 'HelloWorld-exe' for HelloWorld-0.1.0.0..
Building executable 'HelloWorld-exe' for HelloWorld-0.1.0.0..
[1 of 2] Compiling Main ( app/Main.hs, .stack-work/dist/x86_64-linux-tinfo6/Cabal-2.4.0.1/build/HelloWorld-exe/HelloWorld-exe-tmp/Main.o )
[2 of 2] Compiling Paths_HelloWorld ( .stack-work/dist/x86_64-linux-tinfo6/Cabal-2.4.0.1/build/HelloWorld-exe/autogen/Paths_HelloWorld.hs, .stack-work/dist/x86_64-linux-tinfo6/Cabal-2.4.0.1/build/HelloWorld-exe/HelloWorld-exe-tmp/Paths_HelloWorld.o )
Linking .stack-work/dist/x86_64-linux-tinfo6/Cabal-2.4.0.1/build/HelloWorld-exe/HelloWorld-exe ...
HelloWorld-0.1.0.0: copy/register
Installing library in
/home/user/Projects/CTU/FPCourse/files/01_hw_stack/.stack-work/install/x86_64-linux/lts-9.11/8.0.2/lib/x86_64-linux-ghc-8.0.2/HelloWorld-0.1.0.0-GwaTuTuS4ojL8nYytSjUL5
Installing executable(s) in
/home/user/Projects/CTU/FPCourse/files/01_hw_stack/.stack-work/install/x86_64-linux/lts-9.11/8.0.2/bin
Registering HelloWorld-0.1.0.0...
Installing library in /home/user/Projects/MI-AFP/tests/HelloWorld/.stack-work/install/x86_64-linux-tinfo6/lts-13.8/8.6.3/lib/x86_64-linux-ghc-8.6.3/HelloWorld-0.1.0.0-8b39YCi0nmn4QsoDKix2j8
Installing executable HelloWorld-exe in /home/user/Projects/MI-AFP/tests/HelloWorld/.stack-work/install/x86_64-linux-tinfo6/lts-13.8/8.6.3/bin
Registering library for HelloWorld-0.1.0.0..
stack build 6.16s user 0.94s system 96% cpu 7.329 total
```

Everything ended up OK and you are finally able to run the application (`HelloWorld-exe` is defined in `package.yaml`, thus also `HelloWorld.cabal`, and you may change it):

```
```console
% stack exec HelloWorld-exe
Enter your name:
Marek
Expand All @@ -544,18 +560,18 @@ Hello, Marek!

For debugging you can run `ghci` with project preloaded:

```
```console
% stack ghci
Using main module: 1. Package `HelloWorld' component exe:HelloWorld-exe with main-is file: /home/user/Projects/MI-AFP/tests/HelloWorld/app/Main.hs
The following GHC options are incompatible with GHCi and have not been passed to it: -threaded
Configuring GHCi with the following packages: HelloWorld
Using main module: 1. Package `HelloWorld' component exe:HelloWorld-exe with main-is file: /home/.../HelloWorld/app/Main.hs
GHCi, version 8.0.2: http://www.haskell.org/ghc/ :? for help
[1 of 1] Compiling Lib ( /home/.../HelloWorld/src/Lib.hs, interpreted )
Ok, modules loaded: Lib.
[2 of 2] Compiling Main ( /home/.../HelloWorld/app/Main.hs, interpreted )
Ok, modules loaded: Lib, Main.
Loaded GHCi configuration from /tmp/ghci18580/ghci-script
*Main Lib> :browse
GHCi, version 8.6.3: http://www.haskell.org/ghc/ :? for help
[1 of 2] Compiling Lib ( /home/user/Projects/MI-AFP/tests/HelloWorld/src/Lib.hs, interpreted )
[2 of 2] Compiling Main ( /home/user/Projects/MI-AFP/tests/HelloWorld/app/Main.hs, interpreted )
Ok, two modules loaded.
Loaded GHCi configuration from /tmp/haskell-stack-ghci/3b07e5cf/ghci-script
*Main Lib>
:browse
main :: IO ()
*Main Lib> :browse Lib
greet :: String -> String
Expand All @@ -567,7 +583,7 @@ greet :: String -> String

You might have noticed that [Stack] uses `package.yaml` to generate `.cabal` and there is some `stack.yaml`. It also somehow takes care of the needed dependencies. Let's say you need to your collection of type Set. Of course, you could implement it on your own, but reinventing the wheel is unnecessary! Use `Data.Set` which is already here (we will cover details about this and other data structures in Haskell in the future).

If you look up `Data.Set` ([Hoogle], [Hayoo!] or [Hackage]), you will find out that it is in package `containers` licensed under BSD with maintainer email libraries@haskell.org (see [here](http://hackage.haskell.org/package/containers-0.5.11.0/docs/Data-Set.html)). If you now try to do this in your `Lib.hs`:
If you look up `Data.Set` ([Hoogle], [Stackage] or [Hackage]), you will find out that it is in package `containers` licensed under BSD with maintainer email libraries@haskell.org (see [here](http://hackage.haskell.org/package/containers-0.5.11.0/docs/Data-Set.html)). If you now try to do this in your `Lib.hs`:

```haskell
import Data.Set
Expand All @@ -577,7 +593,7 @@ namesSet = insert "Robert" (insert "Marek" empty)

After trying to build with `stack build` you should get this error stating that it could not find module `Data.Set`:

```
```console
/home/.../HelloWorld/src/Lib.hs:5:1: error:
Could not find module ‘Data.Set’
Perhaps you meant Data.Int (from base-4.10.1.0)
Expand Down Expand Up @@ -616,7 +632,7 @@ Further, [Stack] also provides [dependency visualization](https://docs.haskellst

To test out the workflow check the dummy homework [MI-AFP/hw00](https://github.com/MI-AFP/hw00) where you will learn how you should get, complete, check, and submit homework (especially useful if you are not familiar with [GitHub] and [Travis CI]). By working on such homework, you might also learn new things which you encounter in tests and skeletons.

For your first assignment, visit [MI-AFP/hw01](https://github.com/MI-AFP/hw01). The task consists of writing simple expressions, looking up information with [Hoogle], [Hayoo!] and/or GHCi, and working with dependencies of project.
For your first assignment, visit [MI-AFP/hw01](https://github.com/MI-AFP/hw01). The task consists of writing simple expressions, looking up information with [Hoogle], [Stackage], [Hackage] and/or GHCi, and working with dependencies of project.

## Further reading

Expand All @@ -638,7 +654,6 @@ For your first assignment, visit [MI-AFP/hw01](https://github.com/MI-AFP/hw01).
[Haskell 2010]: https://www.haskell.org/onlinereport/haskell2010/
[Haskell Platform]: https://www.haskell.org/platform/
[Haste]: https://haste-lang.org
[Hayoo!]: https://hayoo.fh-wedel.de
[hindent]: https://github.com/commercialhaskell/hindent
[hlint]: https://hackage.haskell.org/package/hlint
[Hoogle]: https://www.haskell.org/hoogle/
Expand Down