diff --git a/tutorials/01_fp-env.md b/tutorials/01_fp-env.md index d4a4834..4b0eda2 100644 --- a/tutorials/01_fp-env.md +++ b/tutorials/01_fp-env.md @@ -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 @@ -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 @@ -72,17 +72,17 @@ 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 @@ -90,22 +90,24 @@ $ cabal install hlint stylish-haskell hindent ghc-mod ### 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. @@ -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. @@ -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 ... @@ -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! ``` @@ -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 ) @@ -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. @@ -481,7 +494,7 @@ 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. @@ -489,7 +502,7 @@ To install the correct GHC into /home/user/.stack/programs/x86_64-linux/, try ru 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. @@ -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 @@ -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 @@ -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 @@ -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) @@ -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 @@ -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/