Resources
1 Course Systems
Here are the key online systems (besides this website!) that we’ll use in the course in rough order of how often you’re likely to use them:
- PrairieLearn
- Most assessments, including quizzes, assignments, and in-class exercises.
- Piazza
- Announcements, discussion, private communication with staff (but use e-mail if you’re uncomfortable using Piazza)
- Panopto
- Lecture recordings (which can also be streamed almost-live)
- Department UNIX servers
- The easiest way to get started with
ghci
(Haskell) andswipl
(Prolog) - Canvas
- Grades (supplementing PrairieLearn), password-protected materials, Zoom for synchronous/live online class, maybe iclicker registration
- More
- Let us know if there’s something else that should be here. Should we talk about learning.github.ubc.ca, replit, or some other useful resource, reference, or slice of awesomeness?
2 Technical Setup
Though we recommend setting up a development environment on your local computer, you are able to develop and run Haskell and Prolog code on the department-provided servers.
2.1 Remote Development
Log in remotely to the students.cs.ubc.ca UNIX servers. (Once you have it set up, ssh MY_CWL_ID@remote.students.cs.ubc.ca
will log you in.) For Haskell, you can run ghci
from the command-line. stack
is also available. For Prolog, you can run swipl
. (Please note that at the time of writing an older version of swipl
is installed. We hope to remedy that soon.)
We have a magic Bash script that you can use on CS servers to make development easier. Add the line source ~cs-312/public/cpsc312_profile.sh
to the bottom of your ~/.bash_profile
. Then open a new shell (or SSH in again) and run cpsc312_init && cpsc312_update
to initialize your dev environment. It will take a while to install all the utils required, so be patient or open it in a tmux session! When it finishes, you’ll find cabal
, doctest
, hlint
, and ghcid
on your path. This script puts the sandboxed ghc
installations and package databases on the scratch drive, so periodically they’ll be wiped. When that happens (and you’ll know because things will act funny) just run cpsc312_reinit && cpsc312_update
.
There are additional functions cpsc312_new_stack
and cpsc312_new_cabal
to make new projects should you need to. However, you can also just work on single files and use ghci
or stack ghci
or cabal repl
(as in the section below on Haskell Interaction).
2.2 Local Editor
You are free to edit code however you want, but we have found that Visual Studio Code works well with some language-specific extensions like
You can install VS Code as their website suggests, or as your package manager allows (e.g. brew install visual-studio-code
).
2.3 Local Haskell Installation
We are using the primary Haskell distribution, GHC. It is available for most major platforms, and installation of the compiler and related tools is now managed by a tool called ghcup. The installer will helpfully prompt you to install the latest versions of components, which you can do safely just by answering “y” or “P” a few times. However, we have found that a slightly older version of GHC is a bit better supported on most platforms. You will find the following tools (at the following versions) useful:
- ghc (8.10.4) - The compiler itself, providing the
ghc
to compile andghci
to run a REPL. (If you must use newer versions in the8.10
series things will generally work fine, modulo somehls
issues. Newer patch releases improve Apple Silicon compatibility.) - stack (2.7.3) - A simple build tool for Haskell projects
- cabal (3.4.0.0) - An advanced build tool for Haskell projects
- hls (optional, 1.3.0) - The Haskell Language Server, essential for the best parts of the Haskell VS Code extension
If you are on Apple Silicon, things are a bit trickier! You will want to use ghc 8.10.7
and not bother yet with hls
. You’ll be fine without the language server - you’ll only miss some IDE features. ghcup upgrade
and ghcup list
will help you track newer releases that may improve compatibility on M1.
ghcup
may ask you to install additional packages for your system. On Windows, you can say yes to installing msys2
. On various linux distributions like Ubuntu or Fedora, it may suggest a number of packages you can install with apt
or yum
- things like build-essential
, libtinfo
, libgmp
, etc. Go ahead and do that.
The versions of these tools in your package manager (apt
, homebrew
, etc.) are likely different from our recommended versions! Therefore, we suggest that you manage these tools with ghcup
. To ensure that these particular versions are installed and configured to be the default, you can run:
$ ghcup install ghc 8.10.4 --set
$ ghcup install stack 2.7.3 --set
$ ghcup install cabal 3.4.0.0 --set
$ ghcup install hls 1.3.0 --set
Finally, you will need to ensure that the binaries for these versions are on your $PATH
. The ghcup installer recommends adding source $HOME/.ghcup/env
to your shell configuration (e.g. in ~/.bash_profile
, ~/.bashrc
, ~/.zprofile
, etc). When you do that and open a new shell, you should be able to do the following:
$ which ghci
/path-to-my-user-home/.ghcup/bin/ghci
$ ghci --version
The Glorious Glasgow Haskell Compilation System, version 8.10.4
Getting your $PATH
correct can be tricky. Remember you have to open a new shell to see configuration changes, and that the order in which directories appear matters! echo $PATH
will help you understand that order, and which ghci
will tell you the first directory in the list that binary comes from. (On Windows, where ghci
may work, or there may be PowerShell equivalents.) If you want to manage your path manually, here’s a good incantation that includes stack
- and cabal
-installed programs on the path too:
export PATH="$HOME/.local/bin:$HOME/.cabal/bin:$HOME/.ghcup/bin:$PATH"
If you try your best and really can’t get it to work, you can try your package manager to install ghc
, stack
, and cabal
, even if they aren’t quite the same versions. (Try Homebrew for Mac, Chocolatey for Windows, apt/yum/dnf/pacman/etc for Linux.) The Haskell Platform has helpful instructions. (However, it’s going to be easiest on your instructors if you can use the versions we recommend; they’re the versions on the remote CS servers.)
2.4 Haskell Interaction
We will walk you through editing and exploring some simple Haskell code. Make a file called Scratch.hs
with the following contents:
module Scratch where
theAnswer :: Int
theAnswer = 42
You can load this file into a REPL like so, and thereafter you can evaluate any Haskell expression:
$ ghci Scratch.hs
GHCi, version 8.10.4: https://www.haskell.org/ghc/ :? for help
[1 of 1] Compiling Scratch ( Scratch.hs, interpreted )
Ok, one module loaded.
*Scratch> theAnswer
42
Note that the list of loaded modules precedes the >
prompt, and that you can simply refer to any member of a loaded module without error. You might try:
import Data.List
- Import the module into scope:type find
- Show the type offind
fromData.List
:doc find
- Show docs forfind
:set prompt >
- Change the prompt to something else (good when you have too many modules listed):reload
- Reload all modules (good for when you edit and saveScratch.hs
):help
- Show everything you can do in GHCI
2.5 Haskell Projects with Stack
If your work gets large enough to split into multiple modules, or if you start needing external dependencies, then you’ll find it easier to do your work in a project. Using a package name my-project
as an example, Run stack new my-project
to scaffold a new project. In your current working directory you will find a new my-project
directory that will contain things like:
.stack-work/
- A directory of artifacts you should git-ignore.package.yaml
- The project definition file. You can set the project name, your name, etc.stack.yaml
- High-level configuration that determines which version of GHC to use and much more. NOTE: We recommend you useresolver: lts-18.6
in this file as of the writing of this guide, with caveats for Apple Silicon.app/Main.hs
- Contains your appmain
function. Can build withstack build
and run withstack exec my-project-exe
.src/Lib.hs
- Contains library code for your app. This can be imported fromapp/Main.hs
ortest/Spec.hs
. Can build withstack build
. You can rename this to something else,src/MyProject.hs
for example, but you’ll need to change the header frommodule Lib ...
tomodule MyProject ...
.test/Spec.hs
- Contains your testmain
function. Can build withstack build
and and run withstack test
.
(Again, please note that the resolver: lts-18.6
settings in stack.yaml
is important if you want to use ghc 8.10.4
. If you want newer releases, then the resolver it picks will work fine.)
Most of the time you’ll start editing in src/Lib.hs
. If you need to add package dependencies from Stackage, add their names to the dependencies:
list in package.yaml
. The following commands are useful:
stack build
- Builds all targetsstack test
- Builds and runs all tests (defined intest/Spec.hs
)stack exec my-project-exe
- Runs the executable defined in theexecutables:
list inpackage.yaml
that is defined inapp/Main.hs
stack ghci
- Enters a REPL with project code and dependencies loadedstack haddock --open
- Opens combined documentation for project and dependencies in your web browser
If you are looking for xUnit-style tests, try tasty with tasty-hunit.
You’ll have to add them to dependencies:
for my-project-test:
in package.yaml
:
dependencies:
- my-project
- tasty
- tasty-hunit
And then you can define test cases in test/Spec.hs
:
-- Import your library code
import Lib
-- Import dependencies
import Test.Tasty
import Test.Tasty.HUnit
main :: IO ()
main = defaultMain $ testGroup "Tests" $
[ testCase "Addition works" $ do
2 + 3 @?= 5 -- actual @?= expected
, testCase "Multiplication works" $ do
6 @=? 2 * 3 -- expected @=? actual
, testCase "Bad assertion" $ do
1 @?= 2
, testCase "Explicit failure" $ do
assertFailure "BOOM!"
]
In this example, the last two test cases will always fail. We can run the “Bad assertion” test case by itself with stack test --test-arguments='--pattern Bad'
.
If you use stack new
a lot, you’ll definitely want to set your name and email in your template variables.
2.6 Local Prolog Installation
We are using a common Prolog distribution, SWI-Prolog. We will use the latest stable version, 8.2.4
. You can install it as they suggest, or as your package manager allows. For example, if you have Homebrew on Mac, you can do brew install swi-prolog
. On Arch, you can do sudo pacman -S swi-prolog
.
2.7 Prolog Interaction
We will walk you through editing and exploring some simple Prolog code. Make a file called scratch.pl
with the following contents:
sunny(tuesday).
barbecue(X) :- sunny(X).
You can load this file into a REPL like so, and thereafter you can evaluate any Prolog expression:
$ swipl scratch.pl
Welcome to SWI-Prolog (threaded, 64 bits, version 8.2.4)
SWI-Prolog comes with ABSOLUTELY NO WARRANTY. This is free software.
Please run ?- license. for legal details.
For online help and background, visit https://www.swi-prolog.org
For built-in help, use ?- help(Topic). or ?- apropos(Word).
?- barbecue(tuesday).
true.
You might try:
make.
- Reloads imports (good for when you edit and savescratch.hs
)help.
- See what the REPL can do
2.8 Other Options
There are a number of online services that let you run snippets of code in a pinch, like
- Try Haskell - This is a great place to learn the basics of Haskell and to try simple expressions
- Code World - Like
Try Haskell
but with some extra functionality to draw pictures - SWISH - A sandbox for SWI-Prolog
3 Haskell Resources
3.1 Readings
For Haskell, we will primarily follow the lectures from CIS 194 by Brent Yorgey this term. CIS 194 links to readings/resources itself, which you’re welcome to use. Where we have specific other assigned or referenced readings, we’ll use the Haskell WikiBook. (Contributing meaningfully to the wikibook would be a great Bonus Point activity!)
Besides CIS 194 and the Haskell WikiBook, there are lots of great (and not-so-great) Haskell resources out there. Consider these free resources:
- Hoogle: not a text/tutorial, but the search engine for Haskell docs
- Real World Haskell: thorough, practical book introducing Haskell
- Learn You a Haskell for Great Good!: whimsical Haskell intro; caution: I find some of the humour off-putting/insulting
- The Haskell documentation includes all the resources above and much more
3.2 Communities
Besides our own Piazza site, there are various communities for learning and help with Haskell, such as Reddit’s r/haskell and its surrounding subreddits.
3.3 More Readings
If you want to nerd-snipe your mind with some of the tremendous depth available in Haskell, consider:
- The Typeclassopedia: an fascinating and challenging tour (by CIS 194’s Brent Yorgey) of Haskell’s powerful type classes, especially those surrounding the infamous Monad.
- Monads and their surroundings in pictures rather than words, code, formulas, and exercises.
- Hakyll: static websites you can debug in Haskell! (Like this one.)
- I’m a nerd, but I cannot get enough of language specifications! Can you? Here’s the Haskell 2010 Language Report.
4 Prolog Resources
The key resources for us include:
- SWI-Prolog is both our prolog implementation and an excellent resource to the documentation, tutorials, and communities available for Prolog
- Learn Prolog Now! is an online textbook for Prolog filled with exercises. The site can be occasionally buggy, and the exercises occasionally very challenging, but it is still a great intro! (And has embedded SWISH Prolog IDEs.)
- UBC’s David Poole and Alan Mackworth introduce you to symbolic AI via Prolog in AI:FCA, particularly Chapter 5, Chapter 13, and Chapter 14.
Some other valuable resources:
- Awesome Prolog Resources list lists useful Prolog references, including much of what is here
- Learn Prolog by building a classic text adventure game
- List of free Books to Learn Prolog
- The Prolog Dictionary is an easy-to-search reference to terminology and predicates in Prolog
- A short tutorial on Prolog with some small examples.
- Coding Guidelines for Prolog (Covington, et al.)
- GNU Prolog, an alternate Prolog implementation
- The ECLiPSe Constraint Programming System and a book: A Gentle Guide to Constraint Logic Programming via ECLiPSe
5 More to add!
We’re still fleshing this out. We’re going to add some notes on:
- Further Prolog interaction