master e6de38f9ece1 cached
35 files
1.6 MB
500.0k tokens
1 requests
Download .txt
Showing preview only (1,731K chars total). Download the full file or copy to clipboard to get everything.
Repository: jamesdbrock/learn-you-a-haskell-notebook
Branch: master
Commit: e6de38f9ece1
Files: 35
Total size: 1.6 MB

Directory structure:
gitextract_njh7ebiu/

├── .devcontainer/
│   ├── Dockerfile
│   └── devcontainer.json
├── .gitignore
├── Dockerfile
├── LICENSE
├── README.md
├── anchordoc/
│   ├── LICENSE
│   ├── README.md
│   ├── Setup.hs
│   ├── anchordoc.cabal
│   ├── notebooks.anchordoc.sh
│   ├── src/
│   │   └── Main.hs
│   └── stack.yaml
├── docker-compose.yml
├── flake.nix
├── kernels/
│   └── haskell.nix
├── kernels.nix
├── notebook/
│   ├── 00-preface.ipynb
│   ├── 01-introduction.ipynb
│   ├── 02-starting-out.ipynb
│   ├── 03-types-and-typeclasses.ipynb
│   ├── 04-syntax-in-functions.ipynb
│   ├── 05-recursion.ipynb
│   ├── 06-higher-order-functions.ipynb
│   ├── 07-modules.ipynb
│   ├── 08-making-our-own-types-and-typeclasses.ipynb
│   ├── 09-input-and-output.ipynb
│   ├── 10-functionally-solving-problems.ipynb
│   ├── 11-functors-applicative-functors-and-monoids.ipynb
│   ├── 12-a-fistful-of-monads.ipynb
│   ├── 13-for-a-few-monads-more.ipynb
│   └── 14-zippers.ipynb
└── notebook_extra/
    ├── WidgetChart.ipynb
    ├── WidgetDiagram.ipynb
    └── WidgetRevival.ipynb

================================================
FILE CONTENTS
================================================

================================================
FILE: .devcontainer/Dockerfile
================================================
FROM ghcr.io/ihaskell/ihaskell-notebook:master


================================================
FILE: .devcontainer/devcontainer.json
================================================
// For format details, see https://aka.ms/devcontainer.json. For config options, see the README at:
// https://github.com/microsoft/vscode-dev-containers/tree/v0.194.0/containers/docker-existing-dockerfile
{
	"name": "IHaskell Community Docker Stack",

	// Sets the run context to one level up instead of the .devcontainer folder.
	"context": "..",

	// Update the 'dockerFile' property if you aren't using the standard 'Dockerfile' filename.
	"dockerFile": "./Dockerfile",

	// Set *default* container specific settings.json values on container create.
	"settings": {},

	// Add the IDs of extensions you want installed when the container is created.
	"extensions": [
		"ms-toolsai.jupyter",
		"haskell.haskell",
		"justusadam.language-haskell",
        // A popup dialog pesters us to install the Python extension if it's not installed.
        // I think this is needed to render errors.
        "ms-python.python"
	]

	// Use 'forwardPorts' to make a list of ports inside the container available locally.
	// "forwardPorts": [],

	// Uncomment the next line to run commands after the container is created - for example installing curl.
	// "postCreateCommand": "apt-get update && apt-get install -y curl",

	// Uncomment when using a ptrace-based debugger like C++, Go, and Rust
	// "runArgs": [ "--cap-add=SYS_PTRACE", "--security-opt", "seccomp=unconfined" ],

	// Uncomment to use the Docker CLI from inside the container. See https://aka.ms/vscode-remote/samples/docker-from-docker.
	// "mounts": [ "source=/var/run/docker.sock,target=/var/run/docker.sock,type=bind" ],

	// Uncomment to connect as a non-root user if you've added one. See https://aka.ms/vscode-remote/containers/non-root.
	// "remoteUser": "vscode"
}


================================================
FILE: .gitignore
================================================
notebook/*.txt
notebook/Geometry.dyn_hi
notebook/Geometry.dyn_o
notebook/Geometry.hi
notebook/Geometry.hs
notebook/Geometry.o
notebook/Geometry/
*/.ipynb_checkpoints
.jupyter/


================================================
FILE: Dockerfile
================================================
# Dockerfile for mybinder.org
#
# Test this Dockerfile:
#
#     docker build -t learn-you-a-haskell .
#     docker run --rm -p 8888:8888 --name learn-you-a-haskell learn-you-a-haskell:latest jupyter lab --ServerApp.token=''
#

FROM ghcr.io/ihaskell/ihaskell-notebook:master@sha256:61ec7f69544bfc59b0f50055c6975509dd0d3c4f40862c771e7407d7272b0274

USER root

RUN mkdir /home/$NB_USER/learn_you_a_haskell
COPY notebook/*.ipynb /home/$NB_USER/learn_you_a_haskell/
COPY notebook/img /home/$NB_USER/learn_you_a_haskell/img
RUN chown --recursive $NB_UID:users /home/$NB_USER/learn_you_a_haskell

ARG EXAMPLES_PATH=/home/$NB_USER/ihaskell_examples
COPY notebook_extra/WidgetRevival.ipynb $EXAMPLES_PATH/
RUN chown $NB_UID:users $EXAMPLES_PATH/WidgetRevival.ipynb

USER $NB_UID

ENV JUPYTER_ENABLE_LAB=yes



================================================
FILE: LICENSE
================================================
https://creativecommons.org/licenses/by-nc-sa/3.0/


================================================
FILE: README.md
================================================
# Learn You a Haskell for Great Good!

## Read the book right now

### Read the book method 1: [mybinder.org](https://mybinder.org/)

Read the book right now on __mybinder.org__ with this link: [![launch Learn You a Haskell for Great Good!](https://img.shields.io/badge/launch-Learn%20You%20A%20Haskell%20For%20Great%20Good!-579ACA.svg?logo=data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAFkAAABZCAMAAABi1XidAAAB8lBMVEX///9XmsrmZYH1olJXmsr1olJXmsrmZYH1olJXmsr1olJXmsrmZYH1olL1olJXmsr1olJXmsrmZYH1olL1olJXmsrmZYH1olJXmsr1olL1olJXmsrmZYH1olL1olJXmsrmZYH1olL1olL0nFf1olJXmsrmZYH1olJXmsq8dZb1olJXmsrmZYH1olJXmspXmspXmsr1olL1olJXmsrmZYH1olJXmsr1olL1olJXmsrmZYH1olL1olLeaIVXmsrmZYH1olL1olL1olJXmsrmZYH1olLna31Xmsr1olJXmsr1olJXmsrmZYH1olLqoVr1olJXmsr1olJXmsrmZYH1olL1olKkfaPobXvviGabgadXmsqThKuofKHmZ4Dobnr1olJXmsr1olJXmspXmsr1olJXmsrfZ4TuhWn1olL1olJXmsqBi7X1olJXmspZmslbmMhbmsdemsVfl8ZgmsNim8Jpk8F0m7R4m7F5nLB6jbh7jbiDirOEibOGnKaMhq+PnaCVg6qWg6qegKaff6WhnpKofKGtnomxeZy3noG6dZi+n3vCcpPDcpPGn3bLb4/Mb47UbIrVa4rYoGjdaIbeaIXhoWHmZYHobXvpcHjqdHXreHLroVrsfG/uhGnuh2bwj2Hxk17yl1vzmljzm1j0nlX1olL3AJXWAAAAbXRSTlMAEBAQHx8gICAuLjAwMDw9PUBAQEpQUFBXV1hgYGBkcHBwcXl8gICAgoiIkJCQlJicnJ2goKCmqK+wsLC4usDAwMjP0NDQ1NbW3Nzg4ODi5+3v8PDw8/T09PX29vb39/f5+fr7+/z8/Pz9/v7+zczCxgAABC5JREFUeAHN1ul3k0UUBvCb1CTVpmpaitAGSLSpSuKCLWpbTKNJFGlcSMAFF63iUmRccNG6gLbuxkXU66JAUef/9LSpmXnyLr3T5AO/rzl5zj137p136BISy44fKJXuGN/d19PUfYeO67Znqtf2KH33Id1psXoFdW30sPZ1sMvs2D060AHqws4FHeJojLZqnw53cmfvg+XR8mC0OEjuxrXEkX5ydeVJLVIlV0e10PXk5k7dYeHu7Cj1j+49uKg7uLU61tGLw1lq27ugQYlclHC4bgv7VQ+TAyj5Zc/UjsPvs1sd5cWryWObtvWT2EPa4rtnWW3JkpjggEpbOsPr7F7EyNewtpBIslA7p43HCsnwooXTEc3UmPmCNn5lrqTJxy6nRmcavGZVt/3Da2pD5NHvsOHJCrdc1G2r3DITpU7yic7w/7Rxnjc0kt5GC4djiv2Sz3Fb2iEZg41/ddsFDoyuYrIkmFehz0HR2thPgQqMyQYb2OtB0WxsZ3BeG3+wpRb1vzl2UYBog8FfGhttFKjtAclnZYrRo9ryG9uG/FZQU4AEg8ZE9LjGMzTmqKXPLnlWVnIlQQTvxJf8ip7VgjZjyVPrjw1te5otM7RmP7xm+sK2Gv9I8Gi++BRbEkR9EBw8zRUcKxwp73xkaLiqQb+kGduJTNHG72zcW9LoJgqQxpP3/Tj//c3yB0tqzaml05/+orHLksVO+95kX7/7qgJvnjlrfr2Ggsyx0eoy9uPzN5SPd86aXggOsEKW2Prz7du3VID3/tzs/sSRs2w7ovVHKtjrX2pd7ZMlTxAYfBAL9jiDwfLkq55Tm7ifhMlTGPyCAs7RFRhn47JnlcB9RM5T97ASuZXIcVNuUDIndpDbdsfrqsOppeXl5Y+XVKdjFCTh+zGaVuj0d9zy05PPK3QzBamxdwtTCrzyg/2Rvf2EstUjordGwa/kx9mSJLr8mLLtCW8HHGJc2R5hS219IiF6PnTusOqcMl57gm0Z8kanKMAQg0qSyuZfn7zItsbGyO9QlnxY0eCuD1XL2ys/MsrQhltE7Ug0uFOzufJFE2PxBo/YAx8XPPdDwWN0MrDRYIZF0mSMKCNHgaIVFoBbNoLJ7tEQDKxGF0kcLQimojCZopv0OkNOyWCCg9XMVAi7ARJzQdM2QUh0gmBozjc3Skg6dSBRqDGYSUOu66Zg+I2fNZs/M3/f/Grl/XnyF1Gw3VKCez0PN5IUfFLqvgUN4C0qNqYs5YhPL+aVZYDE4IpUk57oSFnJm4FyCqqOE0jhY2SMyLFoo56zyo6becOS5UVDdj7Vih0zp+tcMhwRpBeLyqtIjlJKAIZSbI8SGSF3k0pA3mR5tHuwPFoa7N7reoq2bqCsAk1HqCu5uvI1n6JuRXI+S1Mco54YmYTwcn6Aeic+kssXi8XpXC4V3t7/ADuTNKaQJdScAAAAAElFTkSuQmCC)](https://mybinder.org/v2/gh/IHaskell/learn-you-a-haskell-notebook/master?urlpath=lab/tree/learn_you_a_haskell/00-preface.ipynb)
(Usually takes a minute to launch)

### Read the book method 2: [Nix run](https://determinate.systems/posts/nix-run)

```console
nix run github:IHaskell/learn-you-a-haskell-notebook
```

---

![Screenshot](README.screenshot.png)

This is a Jupyter notebook adaptation of the book [__*Learn You a Haskell for Great Good!*__](http://learnyouahaskell.com/) by Miran Lipovača.

I learned Haskell from this book in 2014 by following along in [GHCI](https://downloads.haskell.org/~ghc/latest/docs/html/users_guide/ghci.html), as the book suggested.

In 2019, the [Jupyter](https://jupyter.org/) notebook format would be a nice way read this book. This is one of the best cases for Theodore Gray's idea of the [computational essay](https://www.theatlantic.com/science/archive/2018/04/the-scientific-paper-is-obsolete/556676/), and Andrew Gibiansky has made it possible with [IHaskell](https://github.com/IHaskell/IHaskell).

Each chapter of the book is one `.ipynb` Jupyter notebook file. See the list of chapter files on the left sidebar in JupyterLab.

Each notebook cell depends on cells that come before it, so run the notebooks from top to bottom. I have refactored code to make the examples work in Jupyter, and removed instructions for how to use GHCI. Other than that I have tried to be faithful to the original text.

Miran Lipovača wrote this book and released it to the world under a [Creative Commons Attribution-Noncommercial-Share Alike 3.0 Unported License](http://creativecommons.org/licenses/by-nc-sa/3.0/), which means that the book is free-as-in-speech, and allows us to enjoy the book in notebook format. But that does not mean that the book is free-as-in-beer; it means that you, dear reader, pay for the book under the honor system. If you are honorable and you want to keep living in a world in which honorable artists license their art as Creative Commons, then [buy the book](http://learnyouahaskell.com/).

Thanks also to Paul Vorbach for <https://github.com/pvorb/learn-you-a-haskell>.

# How to run on your local computer in Visual Studio Code

Visual Studio Code has a
[Notebook UI](https://code.visualstudio.com/docs/datascience/jupyter-notebooks)
which you can use to run Jupyter kernels instead of the browser-based
JupyterLab or classic Jupyter UI.

Clone this repository with `git` and `cd` into the cloned directory

```bash
git clone https://github.com/IHaskell/learn-you-a-haskell-notebook.git
cd learn-you-a-haskell-notebook
code .
```

There is a Docker
[Visual Studio Code devcontainer](https://github.com/microsoft/vscode-dev-containers)
configuration in the [`.devcontainer`](.devcontainer) directory.

When you open Visual Studio Code by running `code .`, a pop-up dialog will
tell you that “Folder contains a Dev Container configuration file. Reopen folder
to develop in a container.” Click the button labelled __Reopen in Container__.

You will then be able to open the `.ipynb` chapter files in the `notebook`
directory.

# How to run on your local computer in JupyterLab in a web browser

Clone this repository with `git` and `cd` into the cloned directory

```bash
git clone https://github.com/IHaskell/learn-you-a-haskell-notebook.git
cd learn-you-a-haskell-notebook
```

Then here are three options for running.

1. `docker`

   ```bash
   docker run --rm -p 8888:8888 -v $PWD/notebook:/home/jovyan/work --name learn-you-a-haskell ghcr.io/ihaskell/ihaskell-notebook:master jupyter lab --ServerApp.token=''
   ```

   then open [http://localhost:8888](http://localhost:8888) to read the book.

2. `podman`

   ```bash
   podman run --privileged --userns=keep-id --rm -p 8888:8888 -v $PWD/notebook:/home/jovyan/work --name learn-you-a-haskell ghcr.io/ihaskell/ihaskell-notebook:master jupyter lab --ServerApp.token=''
   ```

   then open [http://localhost:8888](http://localhost:8888) to read the book.

3. [NixOS](https://nixos.org/) flake

   ```
   nix run . -- --notebook-dir notebook
   ```

   then the book will open in a browser automatically. If it doesn’t, open the “running at” link.

# How to edit notebooks

If you make an improvement to a notebook `.ipynb` file and you want to save the file and commit the changes and make a pull request to the repository,

1. Maximize the browser window to full screen width, because cell horizontal scroll bar visibility gets saved in the notebook.

2. Run -> Restart kernel and Run All Cells...

3. Save the notebook.

# ihaskell-notebook

For more information about the IHaskell Docker image, see <https://github.com/IHaskell/ihaskell-notebook>



================================================
FILE: anchordoc/LICENSE
================================================
Copyright James D. Brock (c) 2019

All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

    * Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.

    * Redistributions in binary form must reproduce the above
      copyright notice, this list of conditions and the following
      disclaimer in the documentation and/or other materials provided
      with the distribution.

    * Neither the name of James D. Brock nor the names of other
      contributors may be used to endorse or promote products derived
      from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

================================================
FILE: anchordoc/README.md
================================================
# anchordoc


================================================
FILE: anchordoc/Setup.hs
================================================
import Distribution.Simple
main = defaultMain


================================================
FILE: anchordoc/anchordoc.cabal
================================================
name:                anchordoc
version:             0.1.0.0
-- synopsis:
-- description:
homepage:            https://github.com/jamesdbrock/anchordoc#readme
license:             BSD3
license-file:        LICENSE
author:              James D. Brock
maintainer:          jamesbrock@gmail.com
copyright:           James D. Brock
category:            personal
build-type:          Simple
cabal-version:       >=1.10
extra-source-files:  README.md

executable anchordoc
  hs-source-dirs:      src
  main-is:             Main.hs
  default-language:    Haskell2010
  build-depends:       base >= 4.7 && < 5
                     , megaparsec
                     , split
                     , wreq
                     , aeson
                     , text
                     , lens
                     , lens-aeson
                     , transformers
                     , replace-megaparsec


================================================
FILE: anchordoc/notebooks.anchordoc.sh
================================================
#! /usr/bin/env bash

for n in $(ls ../notebook/*.ipynb); do
    echo $n " ..."
    stack exec anchordoc < $n > ../notebook/tmp
    mv ../notebook/tmp $n
    echo "done"
done


================================================
FILE: anchordoc/src/Main.hs
================================================
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE ViewPatterns #-}

module Main where

import Network.Wreq (getWith, responseBody, param, defaults)
import Control.Lens ((^..), (&), (.~))
import Data.Aeson.Lens
import Data.Text (unpack, pack)
import Text.Megaparsec as Mp
import Replace.Megaparsec

import Data.Void
import Data.Maybe
import Data.Proxy
import Control.Monad

type Parser = Parsec Void String

main :: IO ()
main = do
    getContents >>= streamEditT pattern hoogleReplace >>= putStr
  where
    pattern = match $ eitherP doubleBacktickMask backtickSymbol
    hoogleReplace (orig, Left _) = return orig -- masked by doubleBacktickMask
    hoogleReplace (orig, Right (_, _, "=", _, _)) = return orig -- not acually a symbol
    hoogleReplace (orig, Right (tickPrefix, tickOpen, symbol, tickClose, tickSuffix)) = do

        -- https://github.com/ndmitchell/hoogle/blob/master/docs/API.md#json-api
        --
        -- Query looks like this:
        -- https://hoogle.haskell.org/?mode=json&hoogle=head&scope=package:base&start=1&count=1
        --
        -- Query looks like this:
        -- https://hoogle.haskell.org/?mode=json&hoogle=%3E%3E%3D&scope=package:base&start=1&count=1

        hoogleResult <- flip getWith
                            "https://hoogle.haskell.org"
                            $ defaults
                            & param "mode"   .~ ["json"]
                            & param "hoogle" .~ [pack symbol] -- will be url encoded
                            & param "scope"  .~ ["package:base"]
                            & param "start"  .~ ["1"]
                            & param "count"  .~ ["1"]

        -- Result looks like this:
        -- [
        --   {
        --     "url": "https://hackage.haskell.org/package/base/docs/Prelude.html#v:head",
        --     "module": {
        --       "url": "https://hackage.haskell.org/package/base/docs/Prelude.html",
        --       "name": "Prelude"
        --     },
        --     "package": {
        --       "url": "https://hackage.haskell.org/package/base",
        --       "name": "base"
        --     },
        --     "item": "<span class=name><s0>head</s0></span> :: [a] -&gt; a",
        --     "type": "",
        --     "docs": "Extract the first element of a list, which must be non-empty.\n"
        --   }
        -- ]
        --
        -- Result looks like this:
        -- [
        --   {
        --     "url": "https://hackage.haskell.org/package/base/docs/Prelude.html#v:-62--62--61-",
        --     "module": {
        --       "url": "https://hackage.haskell.org/package/base/docs/Prelude.html",
        --       "name": "Prelude"
        --     },
        --     "package": {
        --       "url": "https://hackage.haskell.org/package/base",
        --       "name": "base"
        --     },
        --     "item": "<span class=name>(<s0>&gt;&gt;=</s0>)</span> :: forall a b . Monad m =&gt; m a -&gt; (a -&gt; m b) -&gt; m b",
        --     "type": "",
        --     "docs": "Sequentially compose two actions, passing any value produced by the\nfirst as an argument to the second.\n"
        --   }
        -- ]

        let hoogleReturnItem = fmap unpack $ listToMaybe $ hoogleResult ^.. responseBody . nth 0 . key "item" . _String

        -- If hoogle returns a documentation URL, and the same symbol
        -- that was queried, then substitute a markdown link
        case
            ( maybe False (==symbol) $ parseMaybe (hoogleReturnItemSymbol :: Parser String) =<< hoogleReturnItem
            , listToMaybe $ hoogleResult ^.. responseBody . nth 0 . key "url" . _String
            ) of
            (True, Just docUrl) ->
                -- Construct a Markdown link with the documentation URL
                return
                    $  tickPrefix
                    ++ "["
                    ++ tickOpen
                    ++ symbol
                    ++ tickClose
                    ++ "]("
                    ++ unpack docUrl
                    ++ ")"
                    ++ tickSuffix
            _ -> return orig

    hoogleReturnItemSymbol :: Parser String
    hoogleReturnItemSymbol = do
        void $ manyTill anySingle $ chunk "<s0>"
        s <- fmap (tokensToChunk (Proxy::Proxy String))
             $ someTill anySingle $ chunk "</s0>"
        void $ takeRest -- must consume all input for parseMaybe success
        return $ streamEdit (chunk "&lt;") (const "<")
               $ streamEdit (chunk "&gt;") (const ">")
               $ streamEdit (chunk "&amp;") (const "&") s

    -- exclude special Markdown backtick escape like ``92 `div` 10``.
    doubleBacktickMask = do
        void $ chunk "``"
        void $ manyTill anySingle $ chunk "``"
        -- we have to succeed and return something or 'sepCap' will backtrack

    -- Parse something that looks like a symbol from Prelude in backticks.
    backtickSymbol = do
        tickPrefix <- noneOf ("[" :: String)
        tickOpen   <- chunk "`"
        symbol     <- Mp.some $ Mp.oneOf $ ['a'..'z'] ++ ['A'..'Z'] ++ "|&?%^*#~.<>+=-$/:'"
        tickClose  <- chunk "`"
        tickSuffix <- noneOf ("]" :: String)
        return ([tickPrefix], tickOpen, symbol, tickClose, [tickSuffix])

-- TODO:
--
-- cases that don't work:
-- infix backtick functions like `elem` in code blocks. we're going to
-- need to only search in "cell-type":"markdown".
--
-- We need to parse only markdown cells, like:
--  {
--    "cell_type": "markdown",
--    "metadata": {},
--    "source": [
--     "__`repeat`__ takes an element and produces an infinite list of just that\n",
--     "element. It's like cycling a list with only one element."
--    ]
--  },
    -- markdownCell :: Parser ()
    -- markdownCell = do
    --     chunk "{"
    --     space
    --     chunk "\"cell_type\": \"markdown\","
    --     space
    --     chunk "\"metadata\": {},"
    --     space
    --     chunk "\"source\": ["
    --     space
    --     chunk "]" >> newline
    --     return ()



================================================
FILE: anchordoc/stack.yaml
================================================
resolver: nightly-2019-09-13


================================================
FILE: docker-compose.yml
================================================
version: '3.3'

services:
   ihaskell-notebook:
     build: .
     ports:
       - "8888:8888"
     volumes:
       - ./notebook:/home/jovyan/work
     restart: always
     environment:
      JUPYTER_ENABLE_LAB: "yes"
      JUPYTER_TOKEN: x



================================================
FILE: flake.nix
================================================
{
  description = "Learn You a Haskell for Great Good! Jupyter adaptation";

  inputs.flake-utils.url = "github:numtide/flake-utils";
  inputs.IHaskell.url = "github:IHaskell/IHaskell";

  nixConfig = {
    extra-substituters = [ "https://ihaskell.cachix.org" ];
    extra-trusted-public-keys = [ "ihaskell.cachix.org-1:WoIvex/Ft/++sjYW3ntqPUL3jDGXIKDpX60pC8d5VLM="];
  };

  outputs = {
    self,
    flake-utils,
    IHaskell,
    ...
  } @ inputs:
    flake-utils.lib.eachDefaultSystem (system:
      let
        pkgs = IHaskell.inputs.nixpkgs24_11.legacyPackages.${system};

        ihaskell-env = IHaskell.packages.${system}.ihaskell-env-display-ghc98;
        notebook-lyah = pkgs.stdenv.mkDerivation {
          name = "notebook-lyah";
          src = ./notebook;
          phases = [ "unpackPhase" "installPhase" ];
          installPhase = ''
            mkdir -p $out
            cp -r $src/* $out/
          '';
        };
      in rec {
        packages = {
          inherit ihaskell-env notebook-lyah;
        };
        apps = {
          default =
            let
              script = pkgs.writeShellApplication {
                name = "jupyter-lab-lyah";
                runtimeInputs = [ ihaskell-env notebook-lyah ];
                text = "jupyter lab --notebook-dir=${notebook-lyah} ${notebook-lyah}/00-preface.ipynb";
              };
            in
            {
              type = "app";
              program = "${script}/bin/jupyter-lab-lyah";
            };
        };
      }
    );
}


================================================
FILE: kernels/haskell.nix
================================================
{
  name,
  availableKernels,
  extraArgs,
}:
availableKernels.haskell {
  inherit name;
  inherit (extraArgs) pkgs;
  displayName = "Haskell";
}


================================================
FILE: kernels.nix
================================================
{pkgs, ...}: {
  # kernel.python.minimal = {
  #   enable = true;
  # };
  kernel.haskell."1" = {
    enable = true;
    displayName = "Haskell";
  };
}


================================================
FILE: notebook/00-preface.ipynb
================================================
{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<img src=\"img/cover.png\" style=\"background-color:white;\"/>\n",
    "\n",
    "Preface to the Jupyter notebook\n",
    "===============================\n",
    "\n",
    "This is a Jupyter notebook adaptation of the book [__*Learn You a Haskell for Great Good!*__](http://learnyouahaskell.com/) by Miran Lipovača.\n",
    "\n",
    "I learned Haskell from this book in 2014 by following along in [GHCI](https://downloads.haskell.org/~ghc/latest/docs/html/users_guide/ghci.html), as the book suggested.\n",
    "\n",
    "In 2019, the Jupyter notebook format would be a nice way read this book. This is one of the best cases for Theodore Gray's idea of the [computational essay](https://www.theatlantic.com/science/archive/2018/04/the-scientific-paper-is-obsolete/556676/), and Andrew Gibiansky has made it possible with [IHaskell](https://github.com/IHaskell/IHaskell).\n",
    "\n",
    "Each chapter of the book is one `.ipynb` Jupyter notebook file. See the list of chapter files on the left sidebar in JupyterLab.\n",
    "\n",
    "Each notebook cell depends on cells that come before it, so run the notebooks from top to bottom. I have refactored code to make the examples work in Jupyter, and removed instructions for how to use GHCI. Other than that I have tried to be faithful to the original text.\n",
    " \n",
    "Miran Lipovača wrote this book and released it to the world under a [Creative Commons Attribution-Noncommercial-Share Alike 3.0 Unported License](http://creativecommons.org/licenses/by-nc-sa/3.0/), which means that the book is free-as-in-speech, and allows us to enjoy the book in notebook format. But that does not mean that the book is free-as-in-beer; it means that you, dear reader, pay for the book under the honor system. If you are honorable and you want to keep living in a world in which honorable artists license their art as Creative Commons, then [buy the book](http://learnyouahaskell.com/).\n",
    "\n",
    "Please fork or contribute or ★ or report bugs on GitHub: <https://github.com/IHaskell/learn-you-a-haskell-notebook>\n",
    "\n",
    "<div style=\"text-align:right;\">\n",
    "James Brock, Tokyo 2019\n",
    "</div>"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Haskell",
   "language": "haskell",
   "name": "haskell"
  },
  "language_info": {
   "codemirror_mode": "ihaskell",
   "file_extension": ".hs",
   "mimetype": "text/x-haskell",
   "name": "haskell",
   "pygments_lexer": "Haskell",
   "version": "9.8.4"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}


================================================
FILE: notebook/01-introduction.ipynb
================================================
{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Introduction\n",
    "============\n",
    "\n",
    "About this tutorial\n",
    "-------------------\n",
    "\n",
    "Welcome to __Learn You a Haskell for Great Good__! If you're reading this,\n",
    "chances are you want to learn Haskell. Well, you've come to the right\n",
    "place, but let's talk about this tutorial a bit first.\n",
    "\n",
    "I decided to write this because I wanted to solidify my own knowledge of\n",
    "Haskell and because I thought I could help people new to Haskell learn\n",
    "it from my perspective. There are quite a few tutorials on Haskell\n",
    "floating around on the internet. When I was starting out in Haskell, I\n",
    "didn't learn from just one resource. The way I learned it was by reading\n",
    "several different tutorials and articles because each explained\n",
    "something in a different way than the other did. By going through\n",
    "several resources, I was able put together the pieces and it all just\n",
    "came falling into place. So this is an attempt at adding another useful\n",
    "resource for learning Haskell so you have a bigger chance of finding one\n",
    "you like.\n",
    "\n",
    "<img src=\"img/bird.png\" title=\"bird\" style=\"float:left;margin-right:2em;background-color:white;\" />\n",
    "\n",
    "This tutorial is aimed at people who have experience in imperative\n",
    "programming languages (C, C++, Java, Python …) but haven't programmed in\n",
    "a functional language before (Haskell, ML, OCaml …). Although I bet that\n",
    "even if you don't have any significant programming experience, a smart\n",
    "person such as yourself will be able to follow along and learn Haskell.\n",
    "\n",
    "The channel \\#haskell on the freenode network is a great place to ask\n",
    "questions if you're feeling stuck. People there are extremely nice,\n",
    "patient and understanding to newbies.\n",
    "\n",
    "I failed to learn Haskell approximately 2 times before finally grasping\n",
    "it because it all just seemed too weird to me and I didn't get it. But\n",
    "then once it just \"clicked\" and after getting over that initial hurdle,\n",
    "it was pretty much smooth sailing. I guess what I'm trying to say is:\n",
    "Haskell is great and if you're interested in programming you should\n",
    "really learn it even if it seems weird at first. Learning Haskell is\n",
    "much like learning to program for the first time — it's fun! It forces\n",
    "you to think differently, which brings us to the next section …\n",
    "\n",
    "So what's Haskell?\n",
    "------------------\n",
    "\n",
    "<img src=\"img/fx.png\" title=\"fx\" style=\"float:right;margin-left:2em;background-color:white;\" /> Haskell is a __purely\n",
    "functional programming language__. In imperative languages you get things\n",
    "done by giving the computer a sequence of tasks and then it executes\n",
    "them. While executing them, it can change state. For instance, you set\n",
    "variable `a` to 5 and then do some stuff and then set it to something\n",
    "else. You have control flow structures for doing some action several\n",
    "times. In purely functional programming you don't tell the computer what\n",
    "to do as such but rather you tell it what stuff *is*. The factorial of a\n",
    "number is the product of all the numbers from 1 to that number, the sum\n",
    "of a list of numbers is the first number plus the sum of all the other\n",
    "numbers, and so on. You express that in the form of functions. You also\n",
    "can't set a variable to something and then set it to something else\n",
    "later. If you say that a is 5, you can't say it's something else later\n",
    "because you just said it was 5. What are you, some kind of liar? So in\n",
    "purely functional languages, a function has no side-effects. The only\n",
    "thing a function can do is calculate something and return it as a\n",
    "result. At first, this seems kind of limiting but it actually has some\n",
    "very nice consequences: if a function is called twice with the same\n",
    "parameters, it's guaranteed to return the same result. That's called\n",
    "referential transparency and not only does it allow the compiler to\n",
    "reason about the program's behavior, but it also allows you to easily\n",
    "deduce (and even prove) that a function is correct and then build more\n",
    "complex functions by gluing simple functions together.\n",
    "\n",
    "<img src=\"img/lazy.png\" title=\"lazy\" style=\"background-color:white;float:right;margin-left:2em;\" /> Haskell is __lazy__. That\n",
    "means that unless specifically told otherwise, Haskell won't execute\n",
    "functions and calculate things until it's really forced to show you a\n",
    "result. That goes well with referential transparency and it allows you\n",
    "to think of programs as a series of __transformations on data__. It also\n",
    "allows cool things such as infinite data structures. Say you have an\n",
    "immutable list of numbers `xs = [1,2,3,4,5,6,7,8]` and a function `doubleMe`\n",
    "which multiplies every element by 2 and then returns a new list. If we\n",
    "wanted to multiply our list by 8 in an imperative language and did\n",
    "`doubleMe(doubleMe(doubleMe(xs)))`, it would probably pass through the\n",
    "list once and make a copy and then return it. Then it would pass through\n",
    "the list another two times and return the result. In a lazy language,\n",
    "calling `doubleMe` on a list without forcing it to show you the result\n",
    "ends up in the program sort of telling you \"Yeah yeah, I'll do it\n",
    "later!\". But once you want to see the result, the first `doubleMe` tells\n",
    "the second one it wants the result, now! The second one says that to the\n",
    "third one and the third one reluctantly gives back a doubled 1, which is\n",
    "a 2. The second one receives that and gives back 4 to the first one. The\n",
    "first one sees that and tells you the first element is 8. So it only\n",
    "does one pass through the list and only when you really need it. That\n",
    "way when you want something from a lazy language you can just take some\n",
    "initial data and efficiently transform and mend it so it resembles what\n",
    "you want at the end.\n",
    "\n",
    "<img src=\"img/boat.png\" title=\"boat\" style=\"background-color:white;float:right;margin-left:2em;\" /> Haskell is __statically\n",
    "typed__. When you compile your program, the compiler knows which piece of\n",
    "code is a number, which is a string and so on. That means that a lot of\n",
    "possible errors are caught at compile time. If you try to add together a\n",
    "number and a string, the compiler will whine at you. Haskell uses a very\n",
    "good type system that has __type inference__. That means that you don't\n",
    "have to explicitly label every piece of code with a type because the\n",
    "type system can intelligently figure out a lot about it. If you say `a =\n",
    "5 + 4`, you don't have to tell Haskell that `a` is a number, it can figure\n",
    "that out by itself. Type inference also allows your code to be more\n",
    "general. If a function you make takes two parameters and adds them\n",
    "together and you don't explicitly state their type, the function will\n",
    "work on any two parameters that act like numbers.\n",
    "\n",
    "Haskell is __elegant and concise__. Because it uses a lot of high level\n",
    "concepts, Haskell programs are usually shorter than their imperative\n",
    "equivalents. And shorter programs are easier to maintain than longer\n",
    "ones and have less bugs.\n",
    "\n",
    "Haskell was made by some __really smart guys__ (with PhDs). Work on\n",
    "Haskell began in 1987 when a committee of researchers got together to\n",
    "design a kick-ass language. In 2003 the Haskell Report was published,\n",
    "which defines a stable version of the language."
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Haskell",
   "language": "haskell",
   "name": "haskell"
  },
  "language_info": {
   "codemirror_mode": "ihaskell",
   "file_extension": ".hs",
   "mimetype": "text/x-haskell",
   "name": "haskell",
   "pygments_lexer": "Haskell",
   "version": "9.2.5"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}


================================================
FILE: notebook/02-starting-out.ipynb
================================================
{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<img src=\"img/startingout.png\" title=\"egg\" style=\"background-color:white;float:right;margin-left:2em;\" /> \n",
    "\n",
    "Starting Out\n",
    "============\n",
    "\n",
    "Ready, set, go!\n",
    "---------------\n",
    "\n",
    "Alright, let's get started!\n",
    "\n",
    "Here are some Jupyter keyboard commands for reading this book. The basic way to read the book is start at the top of each chapter and run each cell by pressing <kbd>Shift</kbd>+<kbd>Enter</kbd>. When you run a Code cell, the result will be printed below the cell. For more information about how to use JuptyerLab, see the top pulldown menus.\n",
    "\n",
    "| Keyboard Command | Action |\n",
    "|-------------:|---------------|\n",
    "|<kbd>Shift</kbd>+<kbd>Enter</kbd> | Run the selected Jupyter cell and advance to the next cell |\n",
    "|<kbd>Ctrl</kbd>+<kbd>Enter</kbd> | Run the selected Jupyter cell and don't advance |\n",
    "|<kbd>Alt</kbd>+<kbd>Enter</kbd> | Run the selected Jupyter cell and insert a new cell after |\n",
    "|<kbd>Enter</kbd> | Edit the selected Jupyter cell |\n",
    "|<kbd>Ctrl</kbd>+<kbd>Shift</kbd>+<kbd>-</kbd> | Split the Jupyter cell at the cursor position |"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "> __Jupyter Note:__ We'll turn off the [automatic linting for IHaskell](https://github.com/IHaskell/IHaskell/wiki#opt-no-lint) first."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {
    "attributes": {
     "classes": [
      "haskell:",
      "ghci"
     ],
     "id": "",
     "name": "\"code\""
    }
   },
   "outputs": [],
   "source": [
    ":opt no-lint"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Here's some simple arithmetic."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {
    "attributes": {
     "classes": [
      "haskell:",
      "ghci"
     ],
     "id": "",
     "name": "\"code\""
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "17"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "2 + 15"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {
    "attributes": {
     "classes": [
      "haskell:",
      "ghci"
     ],
     "id": "",
     "name": "\"code\""
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "4900"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "49 * 100"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {
    "attributes": {
     "classes": [
      "haskell:",
      "ghci"
     ],
     "id": "",
     "name": "\"code\""
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "420"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "1892 - 1472"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {
    "attributes": {
     "classes": [
      "haskell:",
      "ghci"
     ],
     "id": "",
     "name": "\"code\""
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "2.5"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "5 / 2"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "This is pretty self-explanatory. We can also use several operators on\n",
    "one line and all the usual precedence rules are obeyed. We can use\n",
    "parentheses to make the precedence explicit or to change it."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {
    "attributes": {
     "classes": [
      "haskell:",
      "ghci"
     ],
     "id": "",
     "name": "\"code\""
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "1"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "(50 * 100) - 4999"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {
    "attributes": {
     "classes": [
      "haskell:",
      "ghci"
     ],
     "id": "",
     "name": "\"code\""
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "1"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "50 * 100 - 4999"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {
    "attributes": {
     "classes": [
      "haskell:",
      "ghci"
     ],
     "id": "",
     "name": "\"code\""
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "-244950"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "50 * (100 - 4999)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Pretty cool, huh? Yeah, I know it's not but bear with me. A little\n",
    "pitfall to watch out for here is negating numbers. If we want to have a\n",
    "negative number, it's always best to surround it with parentheses. Doing\n",
    "`5 * -3` will make GHC yell at you but doing `5 * (-3)` will work just\n",
    "fine.\n",
    "\n",
    "Boolean algebra is also pretty straightforward. As you probably know, [`&&`](https://hackage.haskell.org/package/base/docs/Prelude.html#v:-38--38-)\n",
    "means a boolean *and*, [`||`](https://hackage.haskell.org/package/base/docs/Prelude.html#v:-124--124-) means a boolean *or*. [`not`](https://hackage.haskell.org/package/base/docs/Prelude.html#v:not) negates a [`True`](https://hackage.haskell.org/package/base/docs/Prelude.html#v:True) or a\n",
    "[`False`](https://hackage.haskell.org/package/base/docs/Prelude.html#v:False)."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {
    "attributes": {
     "classes": [
      "haskell:",
      "ghci"
     ],
     "id": "",
     "name": "\"code\""
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "False"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "True && False"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {
    "attributes": {
     "classes": [
      "haskell:",
      "ghci"
     ],
     "id": "",
     "name": "\"code\""
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "True"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "True && True"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {
    "attributes": {
     "classes": [
      "haskell:",
      "ghci"
     ],
     "id": "",
     "name": "\"code\""
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "True"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "False || True"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {
    "attributes": {
     "classes": [
      "haskell:",
      "ghci"
     ],
     "id": "",
     "name": "\"code\""
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "True"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "not False"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {
    "attributes": {
     "classes": [
      "haskell:",
      "ghci"
     ],
     "id": "",
     "name": "\"code\""
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "False"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "not (True && True)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Testing for equality is done like so."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {
    "attributes": {
     "classes": [
      "haskell:",
      "ghci"
     ],
     "id": "",
     "name": "\"code\""
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "True"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "5 == 5"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {
    "attributes": {
     "classes": [
      "haskell:",
      "ghci"
     ],
     "id": "",
     "name": "\"code\""
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "False"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "1 == 0"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {
    "attributes": {
     "classes": [
      "haskell:",
      "ghci"
     ],
     "id": "",
     "name": "\"code\""
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "False"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "5 /= 5"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {
    "attributes": {
     "classes": [
      "haskell:",
      "ghci"
     ],
     "id": "",
     "name": "\"code\""
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "True"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "5 /= 4"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {
    "attributes": {
     "classes": [
      "haskell:",
      "ghci"
     ],
     "id": "",
     "name": "\"code\""
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "True"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "\"hello\" == \"hello\""
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "What about doing `5 + \"llama\"` or `5 == True`? Well, if we try the first\n",
    "snippet, we get a big scary error message!"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {
    "attributes": {
     "classes": [
      "haskell:",
      "ghci"
     ],
     "id": "",
     "name": "\"code\""
    }
   },
   "outputs": [
    {
     "ename": "",
     "evalue": "",
     "output_type": "error",
     "traceback": [
      "<interactive>:1:3: error:\n    • No instance for (Num String) arising from a use of ‘+’\n    • In the expression: 5 + \"llama\"\n      In an equation for ‘it’: it = 5 + \"llama\""
     ]
    }
   ],
   "source": [
    "5 + \"llama\""
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Yikes! What GHC is telling us here is that `\"llama\"` is not a number and\n",
    "so it doesn't know how to add it to 5. Even if it wasn't `\"llama\"` but\n",
    "`\"four\"` or `\"4\"`, Haskell still wouldn't consider it to be a number. [`+`](https://hackage.haskell.org/package/base/docs/Prelude.html#v:-43-)\n",
    "expects its left and right side to be numbers. If we tried to do `True == 5`,\n",
    "GHC would tell us that the types don't match. Whereas [`+`](https://hackage.haskell.org/package/base/docs/Prelude.html#v:-43-) works only\n",
    "on things that are considered numbers, [`==`](https://hackage.haskell.org/package/base/docs/Prelude.html#v:-61--61-) works on any two things that\n",
    "can be compared. But the catch is that they both have to be the same\n",
    "type of thing. You can't compare apples and oranges. We'll take a closer\n",
    "look at types a bit later. Note: you can do `5 + 4.0` because `5` is sneaky\n",
    "and can act like an integer or a floating-point number. `4.0` can't act\n",
    "like an integer, so `5` is the one that has to adapt.\n",
    "\n",
    "<img src=\"img/ringring.png\" title=\"phoen\" style=\"background-color:white;float:right;margin-left:2em;\" /> \n",
    "You may not have known it but we've been using functions now all along.\n",
    "\n",
    "For instance, [`*`](https://hackage.haskell.org/package/base/docs/Prelude.html#v:-42-) is a function that takes two numbers and multiplies\n",
    "them. As you've seen, we call it by sandwiching it between them. This is\n",
    "what we call an *infix* function. Most functions that aren't used with\n",
    "numbers are *prefix* functions. Let's take a look at them.\n",
    "\n",
    "Functions are\n",
    "usually prefix so from now on we won't explicitly state that a function\n",
    "is of the prefix form, we'll just assume it. In most imperative\n",
    "languages functions are called by writing the function name and then\n",
    "writing its parameters in parentheses, usually separated by commas. In\n",
    "Haskell, functions are called by writing the function name, a space and\n",
    "then the parameters, separated by spaces. For a start, we'll try calling\n",
    "one of the most boring functions in Haskell."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {
    "attributes": {
     "classes": [
      "haskell:",
      "ghci"
     ],
     "id": "",
     "name": "\"code\""
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "9"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "succ 8"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The [`succ`](https://hackage.haskell.org/package/base/docs/Prelude.html#v:succ) function takes anything that has a defined successor and\n",
    "returns that successor. As you can see, we just separate the function\n",
    "name from the parameter with a space. Calling a function with several\n",
    "parameters is also simple. The functions [`min`](https://hackage.haskell.org/package/base/docs/Prelude.html#v:min) and [`max`](https://hackage.haskell.org/package/base/docs/Prelude.html#v:max) take two things\n",
    "that can be put in an order (like numbers!). [`min`](https://hackage.haskell.org/package/base/docs/Prelude.html#v:min) returns the one that's\n",
    "lesser and [`max`](https://hackage.haskell.org/package/base/docs/Prelude.html#v:max) returns the one that's greater. See for yourself:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "metadata": {
    "attributes": {
     "classes": [
      "haskell:",
      "ghci"
     ],
     "id": "",
     "name": "\"code\""
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "9"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "min 9 10"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "metadata": {
    "attributes": {
     "classes": [
      "haskell:",
      "ghci"
     ],
     "id": "",
     "name": "\"code\""
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "3.2"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "min 3.4 3.2"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "metadata": {
    "attributes": {
     "classes": [
      "haskell:",
      "ghci"
     ],
     "id": "",
     "name": "\"code\""
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "101"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "max 100 101"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Function application (calling a function by putting a space after it and\n",
    "then typing out the parameters) has the highest precedence of them all.\n",
    "What that means for us is that these two statements are equivalent."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "metadata": {
    "attributes": {
     "classes": [
      "haskell:",
      "ghci"
     ],
     "id": "",
     "name": "\"code\""
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "16"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "succ 9 + max 5 4 + 1"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "metadata": {
    "attributes": {
     "classes": [
      "haskell:",
      "ghci"
     ],
     "id": "",
     "name": "\"code\""
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "16"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "(succ 9) + (max 5 4) + 1"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "However, if we wanted to get the successor of the product of numbers 9\n",
    "and 10, we couldn't write `succ 9 * 10` because that would get the\n",
    "successor of 9, which would then be multiplied by 10. So 100. We'd have\n",
    "to write `succ (9 * 10)` to get 91.\n",
    "\n",
    "If a function takes two parameters, we can also call it as an infix\n",
    "function by surrounding it with backticks. For instance, the [`div`](https://hackage.haskell.org/package/base/docs/Prelude.html#v:div)\n",
    "function takes two integers and does integral division between them.\n",
    "Doing `div 92 10` results in a 9. But when we call it like that, there may\n",
    "be some confusion as to which number is doing the division and which one\n",
    "is being divided. So we can call it as an infix function by doing\n",
    "``92 `div` 10`` and suddenly it's much clearer.\n",
    "\n",
    "Lots of people who come from imperative languages tend to stick to the\n",
    "notion that parentheses should denote function application. For example,\n",
    "in C, you use parentheses to call functions like `foo()`, `bar(1)` or\n",
    "`baz(3, \"haha\")`. Like we said, spaces are used for function application in\n",
    "Haskell. So those functions in Haskell would be `foo`, `bar 1` and `baz 3\n",
    "\"haha\"`. So if you see something like `bar (bar 3)`, it doesn't mean that\n",
    "`bar` is called with `bar` and `3` as parameters. It means that we first call\n",
    "the function `bar` with `3` as the parameter to get some number and then we\n",
    "call `bar` again with that number. In C, that would be something like\n",
    "`bar(bar(3))`.\n",
    "\n",
    "Baby's first functions\n",
    "----------------------\n",
    "\n",
    "In the previous section we got a basic feel for calling functions. Now\n",
    "let's try making our own!"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "metadata": {
    "attributes": {
     "classes": [
      "haskell:",
      "hs"
     ],
     "id": "",
     "name": "\"code\""
    }
   },
   "outputs": [],
   "source": [
    "doubleMe x = x + x"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Functions are defined in a similar way that they are called. The\n",
    "function name is followed by parameters separated by spaces. But when\n",
    "defining functions, there's a `=` and after that we define what the\n",
    "function does."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "metadata": {
    "attributes": {
     "classes": [
      "haskell:",
      "ghci"
     ],
     "id": "",
     "name": "\"code\""
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "18"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "doubleMe 9"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "metadata": {
    "attributes": {
     "classes": [
      "haskell:",
      "ghci"
     ],
     "id": "",
     "name": "\"code\""
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "16.6"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "doubleMe 8.3"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Because [`+`](https://hackage.haskell.org/package/base/docs/Prelude.html#v:-43-) works on integers as well as on floating-point numbers\n",
    "(anything that can be considered a number, really), our function also\n",
    "works on any number. Let's make a function that takes two numbers and\n",
    "multiplies each by two and then adds them together."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "metadata": {
    "attributes": {
     "classes": [
      "haskell:",
      "hs"
     ],
     "id": "",
     "name": "\"code\""
    }
   },
   "outputs": [],
   "source": [
    "doubleUs x y = x*2 + y*2"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Simple. We could have also defined it as `doubleUs x y = x + x + y + y`.\n",
    "Testing it out produces pretty predictable results."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 30,
   "metadata": {
    "attributes": {
     "classes": [
      "haskell:",
      "ghci"
     ],
     "id": "",
     "name": "\"code\""
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "26"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "doubleUs 4 9"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 31,
   "metadata": {
    "attributes": {
     "classes": [
      "haskell:",
      "ghci"
     ],
     "id": "",
     "name": "\"code\""
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "73.0"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "doubleUs 2.3 34.2"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 32,
   "metadata": {
    "attributes": {
     "classes": [
      "haskell:",
      "ghci"
     ],
     "id": "",
     "name": "\"code\""
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "478"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "doubleUs 28 88 + doubleMe 123"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "As expected, you can call your own functions from other functions that\n",
    "you made. With that in mind, we could redefine `doubleUs` like this:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 33,
   "metadata": {
    "attributes": {
     "classes": [
      "haskell:",
      "hs"
     ],
     "id": "",
     "name": "\"code\""
    }
   },
   "outputs": [],
   "source": [
    "doubleUs x y = doubleMe x + doubleMe y"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "This is a very simple example of a common pattern you will see\n",
    "throughout Haskell. Making basic functions that are obviously correct\n",
    "and then combining them into more complex functions. This way you also\n",
    "avoid repetition. What if some mathematicians figured out that 2 is\n",
    "actually 3 and you had to change your program? You could just redefine\n",
    "`doubleMe` to be `x + x + x` and since `doubleUs` calls `doubleMe`, it would\n",
    "automatically work in this strange new world where 2 is 3.\n",
    "\n",
    "Functions in Haskell don't have to be in any particular order, so it\n",
    "doesn't matter if you define `doubleMe` first and then `doubleUs` or if you\n",
    "do it the other way around.\n",
    "\n",
    "Now we're going to make a function that multiplies a number by 2 but\n",
    "only if that number is smaller than or equal to 100 because numbers\n",
    "bigger than 100 are big enough as it is!"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 34,
   "metadata": {
    "attributes": {
     "classes": [
      "haskell:",
      "hs"
     ],
     "id": "",
     "name": "\"code\""
    }
   },
   "outputs": [],
   "source": [
    "doubleSmallNumber x = if x > 100\n",
    "                        then x\n",
    "                        else x*2"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<img src=\"img/baby.png\" title=\"this is you\" style=\"background-color:white;float:left;margin-right:2em;\"/>\n",
    "\n",
    "Right here we introduced Haskell's if statement. You're probably\n",
    "familiar with if statements from other languages. The difference between\n",
    "Haskell's if statement and if statements in imperative languages is that\n",
    "the else part is mandatory in Haskell. In imperative languages you can\n",
    "just skip a couple of steps if the condition isn't satisfied but in\n",
    "Haskell every expression and function must return something. We could\n",
    "have also written that if statement in one line but I find this way more\n",
    "readable. Another thing about the if statement in Haskell is that it is\n",
    "an *expression*. An expression is basically a piece of code that returns\n",
    "a value. `5` is an expression because it returns 5, `4 + 8` is an\n",
    "expression, `x + y` is an expression because it returns the sum of `x` and\n",
    "`y`. Because the else is mandatory, an if statement will always return\n",
    "something and that's why it's an expression. If we wanted to add one to\n",
    "every number that's produced in our previous function, we could have\n",
    "written its body like this."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 35,
   "metadata": {
    "attributes": {
     "classes": [
      "haskell:",
      "hs"
     ],
     "id": "",
     "name": "\"code\""
    }
   },
   "outputs": [],
   "source": [
    "doubleSmallNumber' x = (if x > 100 then x else x*2) + 1"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Had we omitted the parentheses, it would have added one only if `x` wasn't\n",
    "greater than 100. Note the `'` at the end of the function name. That\n",
    "apostrophe doesn't have any special meaning in Haskell's syntax. It's a\n",
    "valid character to use in a function name. We usually use `'` to either\n",
    "denote a strict version of a function (one that isn't lazy) or a\n",
    "slightly modified version of a function or a variable. Because `'` is a\n",
    "valid character in functions, we can make a function like this."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 36,
   "metadata": {
    "attributes": {
     "classes": [
      "haskell:",
      "hs"
     ],
     "id": "",
     "name": "\"code\""
    }
   },
   "outputs": [],
   "source": [
    "conanO'Brien = \"It's a-me, Conan O'Brien!\""
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "There are two noteworthy things here. The first is that in the function\n",
    "name we didn't capitalize Conan's name. That's because functions can't\n",
    "begin with uppercase letters. We'll see why a bit later. The second\n",
    "thing is that this function doesn't take any parameters. When a function\n",
    "doesn't take any parameters, we usually say it's a *definition* (or a\n",
    "*name*). Because we can't change what names (and functions) mean once\n",
    "we've defined them, `conanO'Brien` and the string `\"It's a-me, Conan\n",
    "O'Brien!\"` can be used interchangeably.\n",
    "\n",
    "An intro to lists\n",
    "-----------------\n",
    "\n",
    "<img src=\"img/list.png\" title=\"BUY A DOG\" style=\"background-color:white;float:left;margin-right:2em\" /> Much like shopping\n",
    "lists in the real world, lists in Haskell are very useful. It's the most\n",
    "used data structure and it can be used in a multitude of different ways\n",
    "to model and solve a whole bunch of problems. Lists are SO awesome. In\n",
    "this section we'll look at the basics of lists, strings (which are\n",
    "lists) and list comprehensions.\n",
    "\n",
    "In Haskell, lists are a *homogenous* data structure. It stores several\n",
    "elements of the same type. That means that we can have a list of\n",
    "integers or a list of characters but we can't have a list that has a few\n",
    "integers and then a few characters. And now, a list!\n",
    "\n",
    "> __Note:__ We can use the `let` keyword to define a name right in GHCI. Doing\n",
    "> `let a = 1` inside GHCI is the equivalent of writing `a = 1` in a script and\n",
    "> then loading it."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 37,
   "metadata": {
    "attributes": {
     "classes": [
      "haskell:",
      "ghci"
     ],
     "id": "",
     "name": "\"code\""
    }
   },
   "outputs": [],
   "source": [
    "let lostNumbers = [4,8,15,16,23,42]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 38,
   "metadata": {
    "attributes": {
     "classes": [
      "haskell:",
      "ghci"
     ],
     "id": "",
     "name": "\"code\""
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[4,8,15,16,23,42]"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "lostNumbers"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "As you can see, lists are denoted by square brackets and the values in\n",
    "the lists are separated by commas. If we tried a list like\n",
    "`[1,2,'a',3,'b','c',4]`, Haskell would complain that characters (which\n",
    "are, by the way, denoted as a character between single quotes) are not\n",
    "numbers. Speaking of characters, strings are just lists of characters.\n",
    "`\"hello\"` is just syntactic sugar for `['h','e','l','l','o']`. Because\n",
    "strings are lists, we can use list functions on them, which is really\n",
    "handy.\n",
    "\n",
    "A common task is putting two lists together. This is done by using the\n",
    "[`++`](https://hackage.haskell.org/package/base/docs/Prelude.html#v:-43--43-) operator."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 39,
   "metadata": {
    "attributes": {
     "classes": [
      "haskell:",
      "ghci"
     ],
     "id": "",
     "name": "\"code\""
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[1,2,3,4,9,10,11,12]"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "[1,2,3,4] ++ [9,10,11,12]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 40,
   "metadata": {
    "attributes": {
     "classes": [
      "haskell:",
      "ghci"
     ],
     "id": "",
     "name": "\"code\""
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "\"hello world\""
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "\"hello\" ++ \" \" ++ \"world\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 41,
   "metadata": {
    "attributes": {
     "classes": [
      "haskell:",
      "ghci"
     ],
     "id": "",
     "name": "\"code\""
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "\"woot\""
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "['w','o'] ++ ['o','t']"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Watch out when repeatedly using the [`++`](https://hackage.haskell.org/package/base/docs/Prelude.html#v:-43--43-) operator on long strings. When\n",
    "you put together two lists (even if you append a singleton list to a\n",
    "list, for instance: `[1,2,3] ++ [4]`), internally, Haskell has to walk\n",
    "through the whole list on the left side of [`++`](https://hackage.haskell.org/package/base/docs/Prelude.html#v:-43--43-). That's not a problem when\n",
    "dealing with lists that aren't too big. But putting something at the end\n",
    "of a list that's fifty million entries long is going to take a while.\n",
    "However, putting something at the beginning of a list using the `:`\n",
    "operator (also called the cons operator) is instantaneous."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 42,
   "metadata": {
    "attributes": {
     "classes": [
      "haskell:",
      "ghci"
     ],
     "id": "",
     "name": "\"code\""
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "\"A SMALL CAT\""
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "'A':\" SMALL CAT\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 43,
   "metadata": {
    "attributes": {
     "classes": [
      "haskell:",
      "ghci"
     ],
     "id": "",
     "name": "\"code\""
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[5,1,2,3,4,5]"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "5:[1,2,3,4,5]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Notice how `:` takes a number and a list of numbers or a character and a\n",
    "list of characters, whereas [`++`](https://hackage.haskell.org/package/base/docs/Prelude.html#v:-43--43-) takes two lists. Even if you're adding an\n",
    "element to the end of a list with [`++`](https://hackage.haskell.org/package/base/docs/Prelude.html#v:-43--43-), you have to surround it with\n",
    "square brackets so it becomes a list.\n",
    "\n",
    "`[1,2,3]` is actually just syntactic sugar for `1:2:3:[]`. `[]` is an empty\n",
    "list. If we prepend `3` to it, it becomes `[3]`. If we prepend `2` to that, it\n",
    "becomes `[2,3]`, and so on.\n",
    "\n",
    "> __Note:__ `[]`, `[[]]` and `[[],[],[]]` are all different things. The first one\n",
    "> is an empty list, the second one is a list that contains one empty list, the\n",
    "> third one is a list that contains three empty lists.\n",
    "\n",
    "If you want to get an element out of a list by index, use `!!`. The\n",
    "indices start at 0."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 44,
   "metadata": {
    "attributes": {
     "classes": [
      "haskell:",
      "ghci"
     ],
     "id": "",
     "name": "\"code\""
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'B'"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "\"Steve Buscemi\" !! 6"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 45,
   "metadata": {
    "attributes": {
     "classes": [
      "haskell:",
      "ghci"
     ],
     "id": "",
     "name": "\"code\""
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "33.2"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "[9.4,33.2,96.2,11.2,23.25] !! 1"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "But if you try to get the sixth element from a list that only has four\n",
    "elements, you'll get an error so be careful!\n",
    "\n",
    "Lists can also contain lists. They can also contain lists that contain\n",
    "lists that contain lists …"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 46,
   "metadata": {
    "attributes": {
     "classes": [
      "haskell:",
      "ghci"
     ],
     "id": "",
     "name": "\"code\""
    }
   },
   "outputs": [],
   "source": [
    "let b = [[1,2,3,4],[5,3,3,3],[1,2,2,3,4],[1,2,3]]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 47,
   "metadata": {
    "attributes": {
     "classes": [
      "haskell:",
      "ghci"
     ],
     "id": "",
     "name": "\"code\""
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[[1,2,3,4],[5,3,3,3],[1,2,2,3,4],[1,2,3]]"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "b"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 48,
   "metadata": {
    "attributes": {
     "classes": [
      "haskell:",
      "ghci"
     ],
     "id": "",
     "name": "\"code\""
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[[1,2,3,4],[5,3,3,3],[1,2,2,3,4],[1,2,3],[1,1,1,1]]"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "b ++ [[1,1,1,1]]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 49,
   "metadata": {
    "attributes": {
     "classes": [
      "haskell:",
      "ghci"
     ],
     "id": "",
     "name": "\"code\""
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[[6,6,6],[1,2,3,4],[5,3,3,3],[1,2,2,3,4],[1,2,3]]"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "[6,6,6]:b"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 50,
   "metadata": {
    "attributes": {
     "classes": [
      "haskell:",
      "ghci"
     ],
     "id": "",
     "name": "\"code\""
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[1,2,2,3,4]"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "b !! 2"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The lists within a list can be of different lengths but they can't be of\n",
    "different types. Just like you can't have a list that has some\n",
    "characters and some numbers, you can't have a list that has some lists\n",
    "of characters and some lists of numbers.\n",
    "\n",
    "Lists can be compared if the stuff they contain can be compared. When\n",
    "using [`<`](https://hackage.haskell.org/package/base/docs/Prelude.html#v:-60-), [`<=`](https://hackage.haskell.org/package/base/docs/Prelude.html#v:-60--61-), [`>`](https://hackage.haskell.org/package/base/docs/Prelude.html#v:-62-) and [`>=`](https://hackage.haskell.org/package/base/docs/Prelude.html#v:-62--61-) to compare lists, they are compared in\n",
    "lexicographical order. First the heads are compared. If they are equal\n",
    "then the second elements are compared, etc."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 51,
   "metadata": {
    "attributes": {
     "classes": [
      "haskell:",
      "ghci"
     ],
     "id": "",
     "name": "\"code\""
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "True"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "[3,2,1] > [2,1,0]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 52,
   "metadata": {
    "attributes": {
     "classes": [
      "haskell:",
      "ghci"
     ],
     "id": "",
     "name": "\"code\""
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "True"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "[3,2,1] > [2,10,100]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 53,
   "metadata": {
    "attributes": {
     "classes": [
      "haskell:",
      "ghci"
     ],
     "id": "",
     "name": "\"code\""
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "True"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "[3,4,2] > [3,4]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 54,
   "metadata": {
    "attributes": {
     "classes": [
      "haskell:",
      "ghci"
     ],
     "id": "",
     "name": "\"code\""
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "True"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "[3,4,2] > [2,4]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 55,
   "metadata": {
    "attributes": {
     "classes": [
      "haskell:",
      "ghci"
     ],
     "id": "",
     "name": "\"code\""
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "True"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "[3,4,2] == [3,4,2]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "What else can you do with lists? Here are some basic functions that\n",
    "operate on lists.\n",
    "\n",
    "__[`head`](https://hackage.haskell.org/package/base/docs/Prelude.html#v:head)__ takes a list and returns its head. The head of a list is basically\n",
    "its first element."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 56,
   "metadata": {
    "attributes": {
     "classes": [
      "haskell:",
      "ghci"
     ],
     "id": "",
     "name": "\"code\""
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "5"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "head [5,4,3,2,1]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "__[`tail`](https://hackage.haskell.org/package/base/docs/Prelude.html#v:tail)__ takes a list and returns its tail. In other words, it chops off a\n",
    "list's head."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 57,
   "metadata": {
    "attributes": {
     "classes": [
      "haskell:",
      "ghci"
     ],
     "id": "",
     "name": "\"code\""
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[4,3,2,1]"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "tail [5,4,3,2,1]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "__[`last`](https://hackage.haskell.org/package/base/docs/Prelude.html#v:last)__ takes a list and returns its last element."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 58,
   "metadata": {
    "attributes": {
     "classes": [
      "haskell:",
      "ghci"
     ],
     "id": "",
     "name": "\"code\""
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "1"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "last [5,4,3,2,1]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "__[`init`](https://hackage.haskell.org/package/base/docs/Prelude.html#v:init)__ takes a list and returns everything except its last element."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 59,
   "metadata": {
    "attributes": {
     "classes": [
      "haskell:",
      "ghci"
     ],
     "id": "",
     "name": "\"code\""
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[5,4,3,2]"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "init [5,4,3,2,1]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "If we think of a list as a monster, here's what's what.\n",
    "\n",
    "<img src=\"img/listmonster.png\" title=\"list monster\" style=\"background-color:white;\" />\n",
    "\n",
    "But what happens if we try to get the head of an empty list?"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 60,
   "metadata": {
    "attributes": {
     "classes": [
      "haskell:",
      "ghci"
     ],
     "id": "",
     "name": "\"code\""
    }
   },
   "outputs": [
    {
     "ename": "",
     "evalue": "",
     "output_type": "error",
     "traceback": [
      "Prelude.head: empty list"
     ]
    }
   ],
   "source": [
    "head []"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Oh my! It all blows up in our face! If there's no monster, it doesn't\n",
    "have a head. When using [`head`](https://hackage.haskell.org/package/base/docs/Prelude.html#v:head), [`tail`](https://hackage.haskell.org/package/base/docs/Prelude.html#v:tail), [`last`](https://hackage.haskell.org/package/base/docs/Prelude.html#v:last) and [`init`](https://hackage.haskell.org/package/base/docs/Prelude.html#v:init), be careful not to use\n",
    "them on empty lists. This error cannot be caught at compile time so it's\n",
    "always good practice to take precautions against accidentally telling\n",
    "Haskell to give you some elements from an empty list.\n",
    "\n",
    "__[`length`](https://hackage.haskell.org/package/base/docs/Prelude.html#v:length)__ takes a list and returns its length, obviously."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 61,
   "metadata": {
    "attributes": {
     "classes": [
      "haskell:",
      "ghci"
     ],
     "id": "",
     "name": "\"code\""
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "5"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "length [5,4,3,2,1]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "__[`null`](https://hackage.haskell.org/package/base/docs/Prelude.html#v:null)__ checks if a list is empty. If it is, it returns [`True`](https://hackage.haskell.org/package/base/docs/Prelude.html#v:True), otherwise it\n",
    "returns [`False`](https://hackage.haskell.org/package/base/docs/Prelude.html#v:False). Use this function instead of `xs == []` (if you have a list\n",
    "called `xs`)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 62,
   "metadata": {
    "attributes": {
     "classes": [
      "haskell:",
      "ghci"
     ],
     "id": "",
     "name": "\"code\""
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "False"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "null [1,2,3]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 63,
   "metadata": {
    "attributes": {
     "classes": [
      "haskell:",
      "ghci"
     ],
     "id": "",
     "name": "\"code\""
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "True"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "null []"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "__[`reverse`](https://hackage.haskell.org/package/base/docs/Prelude.html#v:reverse)__ reverses a list."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 64,
   "metadata": {
    "attributes": {
     "classes": [
      "haskell:",
      "ghci"
     ],
     "id": "",
     "name": "\"code\""
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[1,2,3,4,5]"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "reverse [5,4,3,2,1]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "__[`take`](https://hackage.haskell.org/package/base/docs/Prelude.html#v:take)__ takes number and a list. It extracts that many elements from the\n",
    "beginning of the list. Watch."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 65,
   "metadata": {
    "attributes": {
     "classes": [
      "haskell:",
      "ghci"
     ],
     "id": "",
     "name": "\"code\""
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[5,4,3]"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "take 3 [5,4,3,2,1]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 66,
   "metadata": {
    "attributes": {
     "classes": [
      "haskell:",
      "ghci"
     ],
     "id": "",
     "name": "\"code\""
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[3]"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "take 1 [3,9,3]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 67,
   "metadata": {
    "attributes": {
     "classes": [
      "haskell:",
      "ghci"
     ],
     "id": "",
     "name": "\"code\""
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[1,2]"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "take 5 [1,2]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 68,
   "metadata": {
    "attributes": {
     "classes": [
      "haskell:",
      "ghci"
     ],
     "id": "",
     "name": "\"code\""
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[]"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "take 0 [6,6,6]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "See how if we try to take more elements than there are in the list, it\n",
    "just returns the list. If we try to take 0 elements, we get an empty\n",
    "list.\n",
    "\n",
    "__[`drop`](https://hackage.haskell.org/package/base/docs/Prelude.html#v:drop)__ works in a similar way, only it drops the number of elements from\n",
    "the beginning of a list."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 69,
   "metadata": {
    "attributes": {
     "classes": [
      "haskell:",
      "ghci"
     ],
     "id": "",
     "name": "\"code\""
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[1,5,6]"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "drop 3 [8,4,2,1,5,6]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 70,
   "metadata": {
    "attributes": {
     "classes": [
      "haskell:",
      "ghci"
     ],
     "id": "",
     "name": "\"code\""
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[1,2,3,4]"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "drop 0 [1,2,3,4]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 71,
   "metadata": {
    "attributes": {
     "classes": [
      "haskell:",
      "ghci"
     ],
     "id": "",
     "name": "\"code\""
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[]"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "drop 100 [1,2,3,4]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "__[`maximum`](https://hackage.haskell.org/package/base/docs/Prelude.html#v:maximum)__ takes a list of stuff that can be put in some kind of order and\n",
    "returns the biggest element.\n",
    "\n",
    "__[`minimum`](https://hackage.haskell.org/package/base/docs/Prelude.html#v:minimum)__ returns the smallest."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 72,
   "metadata": {
    "attributes": {
     "classes": [
      "haskell:",
      "ghci"
     ],
     "id": "",
     "name": "\"code\""
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "1"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "minimum [8,4,2,1,5,6]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 73,
   "metadata": {
    "attributes": {
     "classes": [
      "haskell:",
      "ghci"
     ],
     "id": "",
     "name": "\"code\""
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "9"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "maximum [1,9,2,3,4]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "__[`sum`](https://hackage.haskell.org/package/base/docs/Prelude.html#v:sum)__ takes a list of numbers and returns their sum.\n",
    "\n",
    "__[`product`](https://hackage.haskell.org/package/base/docs/Prelude.html#v:product)__ takes a list of numbers and returns their product."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 74,
   "metadata": {
    "attributes": {
     "classes": [
      "haskell:",
      "ghci"
     ],
     "id": "",
     "name": "\"code\""
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "31"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "sum [5,2,1,6,3,2,5,7]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 75,
   "metadata": {
    "attributes": {
     "classes": [
      "haskell:",
      "ghci"
     ],
     "id": "",
     "name": "\"code\""
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "24"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "product [6,2,1,2]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 76,
   "metadata": {
    "attributes": {
     "classes": [
      "haskell:",
      "ghci"
     ],
     "id": "",
     "name": "\"code\""
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "0"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "product [1,2,5,6,7,9,2,0]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "__[`elem`](https://hackage.haskell.org/package/base/docs/Prelude.html#v:elem)__ takes a thing and a list of things and tells us if that thing is an\n",
    "element of the list. It's usually called as an infix function because\n",
    "it's easier to read that way."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 77,
   "metadata": {
    "attributes": {
     "classes": [
      "haskell:",
      "ghci"
     ],
     "id": "",
     "name": "\"code\""
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "True"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "4 `elem` [3,4,5,6]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 78,
   "metadata": {
    "attributes": {
     "classes": [
      "haskell:",
      "ghci"
     ],
     "id": "",
     "name": "\"code\""
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "False"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "10 `elem` [3,4,5,6]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Those were a few basic functions that operate on lists. We'll take a\n",
    "look at more list functions [later](http://learnyouahaskell.com/modules#data-list)\n",
    "\n",
    "Texas ranges\n",
    "------------\n",
    "\n",
    "<img src=\"img/cowboy.png\" title=\"draw\" style=\"background-color:white;float:right;margin-left:2em;\" /> What if we want a list\n",
    "of all numbers between 1 and 20? Sure, we could just type them all out\n",
    "but obviously that's not a solution for gentlemen who demand excellence\n",
    "from their programming languages. Instead, we'll use ranges. Ranges are\n",
    "a way of making lists that are arithmetic sequences of elements that can\n",
    "be enumerated. Numbers can be enumerated. One, two, three, four, etc.\n",
    "Characters can also be enumerated. The alphabet is an enumeration of\n",
    "characters from A to Z. Names can't be enumerated. What comes after\n",
    "\"John\"? I don't know.\n",
    "\n",
    "To make a list containing all the natural numbers from 1 to 20, you just\n",
    "write `[1..20]`. That is the equivalent of writing\n",
    "`[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20]` and there's no\n",
    "difference between writing one or the other except that writing out long\n",
    "enumeration sequences manually is stupid."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 79,
   "metadata": {
    "attributes": {
     "classes": [
      "haskell:",
      "ghci"
     ],
     "id": "",
     "name": "\"code\""
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20]"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "[1..20]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 80,
   "metadata": {
    "attributes": {
     "classes": [
      "haskell:",
      "ghci"
     ],
     "id": "",
     "name": "\"code\""
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "\"abcdefghijklmnopqrstuvwxyz\""
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "['a'..'z']"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 81,
   "metadata": {
    "attributes": {
     "classes": [
      "haskell:",
      "ghci"
     ],
     "id": "",
     "name": "\"code\""
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "\"KLMNOPQRSTUVWXYZ\""
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "['K'..'Z']"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Ranges are cool because you can also specify a step. What if we want all\n",
    "even numbers between 1 and 20? Or every third number between 1 and 20?"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 82,
   "metadata": {
    "attributes": {
     "classes": [
      "haskell:",
      "ghci"
     ],
     "id": "",
     "name": "\"code\""
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[2,4,6,8,10,12,14,16,18,20]"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "[2,4..20]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 83,
   "metadata": {
    "attributes": {
     "classes": [
      "haskell:",
      "ghci"
     ],
     "id": "",
     "name": "\"code\""
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[3,6,9,12,15,18]"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "[3,6..20]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "It's simply a matter of separating the first two elements with a comma\n",
    "and then specifying what the upper limit is. While pretty smart, ranges\n",
    "with steps aren't as smart as some people expect them to be. You can't\n",
    "do `[1,2,4,8,16..100]` and expect to get all the powers of 2. Firstly\n",
    "because you can only specify one step. And secondly because some\n",
    "sequences that aren't arithmetic are ambiguous if given only by a few of\n",
    "their first terms.\n",
    "\n",
    "To make a list with all the numbers from 20 to 1, you can't just do\n",
    "`[20..1]`, you have to do `[20,19..1]`.\n",
    "\n",
    "Watch out when using floating point numbers in ranges! Because they are\n",
    "not completely precise (by definition), their use in ranges can yield\n",
    "some pretty funky results."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 84,
   "metadata": {
    "attributes": {
     "classes": [
      "haskell:",
      "ghci"
     ],
     "id": "",
     "name": "\"code\""
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[0.1,0.3,0.5,0.7,0.8999999999999999,1.0999999999999999]"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "[0.1, 0.3 .. 1]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "My advice is not to use them in list ranges.\n",
    "\n",
    "You can also use ranges to make infinite lists by just not specifying an\n",
    "upper limit. Later we'll go into more detail on infinite lists. For now,\n",
    "let's examine how you would get the first 24 multiples of 13. Sure, you\n",
    "could do `[13,26..24*13]`. But there's a better way: `take 24 [13,26..]`.\n",
    "Because Haskell is lazy, it won't try to evaluate the infinite list\n",
    "immediately because it would never finish. It'll wait to see what you\n",
    "want to get out of that infinite lists. And here it sees you just want\n",
    "the first 24 elements and it gladly obliges.\n",
    "\n",
    "A handful of functions that produce infinite lists:\n",
    "\n",
    "__[`cycle`](https://hackage.haskell.org/package/base/docs/Prelude.html#v:cycle)__ takes a list and cycles it into an infinite list. If you just try\n",
    "to display the result, it will go on forever so you have to slice it off\n",
    "somewhere."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 85,
   "metadata": {
    "attributes": {
     "classes": [
      "haskell:",
      "ghci"
     ],
     "id": "",
     "name": "\"code\""
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[1,2,3,1,2,3,1,2,3,1]"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "take 10 (cycle [1,2,3])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 86,
   "metadata": {
    "attributes": {
     "classes": [
      "haskell:",
      "ghci"
     ],
     "id": "",
     "name": "\"code\""
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "\"LOL LOL LOL \""
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "take 12 (cycle \"LOL \")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "__[`repeat`](https://hackage.haskell.org/package/base/docs/Prelude.html#v:repeat)__ takes an element and produces an infinite list of just that\n",
    "element. It's like cycling a list with only one element."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 87,
   "metadata": {
    "attributes": {
     "classes": [
      "haskell:",
      "ghci"
     ],
     "id": "",
     "name": "\"code\""
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[5,5,5,5,5,5,5,5,5,5]"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "take 10 (repeat 5)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Although it's simpler to just use the [`replicate`](https://hackage.haskell.org/package/base/docs/Prelude.html#v:replicate) function if you want\n",
    "some number of the same element in a list. `replicate 3 10` returns\n",
    "`[10,10,10]`.\n",
    "\n",
    "<a name=\"im-a-list-comprehension\"></a>\n",
    "\n",
    "I'm a list comprehension\n",
    "------------------------\n",
    "\n",
    "<img src=\"img/kermit.png\" title=\"frog\" style=\"background-color:white;float:left;margin-right:2em;\" /> If you've ever taken a\n",
    "course in mathematics, you've probably run into *set comprehensions*.\n",
    "They're normally used for building more specific sets out of general\n",
    "sets. A basic comprehension for a set that contains the first ten even\n",
    "natural numbers is $ S=\\{2 \\centerdot x | x \\in \\mathbb{N}, x \\le 10 \\}$. The part before\n",
    "the pipe is called the output function, `x` is the variable, `N` is the\n",
    "input set and `x <= 10` is the predicate. That means that the set\n",
    "contains the doubles of all natural numbers that satisfy the predicate.\n",
    "\n",
    "If we wanted to write that in Haskell, we could do something like `take\n",
    "10 [2,4..]`. But what if we didn't want doubles of the first 10 natural\n",
    "numbers but some kind of more complex function applied on them? We could\n",
    "use a list comprehension for that. List comprehensions are very similar\n",
    "to set comprehensions. We'll stick to getting the first 10 even numbers\n",
    "for now. The list comprehension we could use is `[x*2 | x <- [1..10]]`.\n",
    "`x` is drawn from `[1..10]` and for every element in `[1..10]` (which we have\n",
    "bound to `x`), we get that element, only doubled. Here's that\n",
    "comprehension in action."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 88,
   "metadata": {
    "attributes": {
     "classes": [
      "haskell:",
      "ghci"
     ],
     "id": "",
     "name": "\"code\""
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[2,4,6,8,10,12,14,16,18,20]"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "[x*2 | x <- [1..10]]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "As you can see, we get the desired results. Now let's add a condition\n",
    "(or a predicate) to that comprehension. Predicates go after the binding\n",
    "parts and are separated from them by a comma. Let's say we want only the\n",
    "elements which, doubled, are greater than or equal to 12."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 89,
   "metadata": {
    "attributes": {
     "classes": [
      "haskell:",
      "ghci"
     ],
     "id": "",
     "name": "\"code\""
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[12,14,16,18,20]"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "[x*2 | x <- [1..10], x*2 >= 12]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Cool, it works. How about if we wanted all numbers from 50 to 100 whose\n",
    "remainder when divided with the number 7 is 3? Easy."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 90,
   "metadata": {
    "attributes": {
     "classes": [
      "haskell:",
      "ghci"
     ],
     "id": "",
     "name": "\"code\""
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[52,59,66,73,80,87,94]"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "[ x | x <- [50..100], x `mod` 7 == 3]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Success! Note that weeding out lists by predicates is also called\n",
    "*filtering*. We took a list of numbers and we filtered them by the\n",
    "predicate. Now for another example. Let's say we want a comprehension\n",
    "that replaces each odd number greater than 10 with `\"BANG!\"` and each odd\n",
    "number that's less than 10 with `\"BOOM!\"`. If a number isn't odd, we throw\n",
    "it out of our list. For convenience, we'll put that comprehension inside\n",
    "a function so we can easily reuse it."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 91,
   "metadata": {
    "attributes": {
     "classes": [
      "haskell:",
      "ghci"
     ],
     "id": "",
     "name": "\"code\""
    }
   },
   "outputs": [],
   "source": [
    "boomBangs xs = [ if x < 10 then \"BOOM!\" else \"BANG!\" | x <- xs, odd x]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The last part of the comprehension is the predicate. The function [`odd`](https://hackage.haskell.org/package/base/docs/Prelude.html#v:odd)\n",
    "returns [`True`](https://hackage.haskell.org/package/base/docs/Prelude.html#v:True) on an odd number and [`False`](https://hackage.haskell.org/package/base/docs/Prelude.html#v:False) on an even one. The element is\n",
    "included in the list only if all the predicates evaluate to [`True`](https://hackage.haskell.org/package/base/docs/Prelude.html#v:True)."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 92,
   "metadata": {
    "attributes": {
     "classes": [
      "haskell:",
      "hs"
     ],
     "id": "",
     "name": "\"code\""
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[\"BOOM!\",\"BOOM!\",\"BANG!\",\"BANG!\"]"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "boomBangs [7..13]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We can include several predicates. If we wanted all numbers from 10 to\n",
    "20 that are not 13, 15 or 19, we'd do:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 93,
   "metadata": {
    "attributes": {
     "classes": [
      "haskell:",
      "ghci"
     ],
     "id": "",
     "name": "\"code\""
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[10,11,12,14,16,17,18,20]"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "[ x | x <- [10..20], x /= 13, x /= 15, x /= 19]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Not only can we have multiple predicates in list comprehensions (an\n",
    "element must satisfy all the predicates to be included in the resulting\n",
    "list), we can also draw from several lists. When drawing from several\n",
    "lists, comprehensions produce all combinations of the given lists and\n",
    "then join them by the output function we supply. A list produced by a\n",
    "comprehension that draws from two lists of length 4 will have a length\n",
    "of 16, provided we don't filter them. If we have two lists, `[2,5,10]` and\n",
    "`[8,10,11]` and we want to get the products of all the possible\n",
    "combinations between numbers in those lists, here's what we'd do."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 94,
   "metadata": {
    "attributes": {
     "classes": [
      "haskell:",
      "ghci"
     ],
     "id": "",
     "name": "\"code\""
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[16,20,22,40,50,55,80,100,110]"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "[ x*y | x <- [2,5,10], y <- [8,10,11]]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "As expected, the length of the new list is 9. What if we wanted all\n",
    "possible products that are more than 50?"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 95,
   "metadata": {
    "attributes": {
     "classes": [
      "haskell:",
      "ghci"
     ],
     "id": "",
     "name": "\"code\""
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[55,80,100,110]"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "[ x*y | x <- [2,5,10], y <- [8,10,11], x*y > 50]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "How about a list comprehension that combines a list of adjectives and a\n",
    "list of nouns … for epic hilarity."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 96,
   "metadata": {
    "attributes": {
     "classes": [
      "haskell:",
      "ghci"
     ],
     "id": "",
     "name": "\"code\""
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[\"lazy hobo\",\"lazy frog\",\"lazy pope\",\"grouchy hobo\",\"grouchy frog\",\"grouchy pope\",\"scheming hobo\",\"scheming frog\",\"scheming pope\"]"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "let nouns = [\"hobo\",\"frog\",\"pope\"]\n",
    "let adjectives = [\"lazy\",\"grouchy\",\"scheming\"]\n",
    "[adjective ++ \" \" ++ noun | adjective <- adjectives, noun <- nouns]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "I know! Let's write our own version of [`length`](https://hackage.haskell.org/package/base/docs/Prelude.html#v:length)! We'll call it `length'`."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 97,
   "metadata": {
    "attributes": {
     "classes": [
      "haskell:",
      "hs"
     ],
     "id": "",
     "name": "\"code\""
    }
   },
   "outputs": [],
   "source": [
    "length' xs = sum [1 | _ <- xs]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "`_` means that we don't care what we'll draw from the list anyway so\n",
    "instead of writing a variable name that we'll never use, we just write\n",
    "`_`. This function replaces every element of a list with `1` and then sums\n",
    "that up. This means that the resulting sum will be the length of our\n",
    "list.\n",
    "\n",
    "Just a friendly reminder: because strings are lists, we can use list\n",
    "comprehensions to process and produce strings. Here's a function that\n",
    "takes a string and removes everything except uppercase letters from it."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 98,
   "metadata": {
    "attributes": {
     "classes": [
      "haskell:",
      "hs"
     ],
     "id": "",
     "name": "\"code\""
    }
   },
   "outputs": [],
   "source": [
    "removeNonUppercase st = [ c | c <- st, c `elem` ['A'..'Z']]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Testing it out:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 99,
   "metadata": {
    "attributes": {
     "classes": [
      "haskell:",
      "ghci"
     ],
     "id": "",
     "name": "\"code\""
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "\"HA\""
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "removeNonUppercase \"Hahaha! Ahahaha!\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 100,
   "metadata": {
    "attributes": {
     "classes": [
      "haskell:",
      "ghci"
     ],
     "id": "",
     "name": "\"code\""
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "\"ILIKEFROGS\""
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "removeNonUppercase \"IdontLIKEFROGS\""
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The predicate here does all the work. It says that the character will be\n",
    "included in the new list only if it's an element of the list `['A'..'Z']`.\n",
    "Nested list comprehensions are also possible if you're operating on\n",
    "lists that contain lists. A list contains several lists of numbers.\n",
    "Let's remove all odd numbers without flattening the list."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 101,
   "metadata": {
    "attributes": {
     "classes": [
      "haskell:",
      "ghci"
     ],
     "id": "",
     "name": "\"code\""
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[[2,2,4],[2,4,6,8],[2,4,2,6,2,6]]"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "let xxs = [[1,3,5,2,3,1,2,4,5],[1,2,3,4,5,6,7,8,9],[1,2,4,2,1,6,3,1,3,2,3,6]]\n",
    "[ [ x | x <- xs, even x ] | xs <- xxs]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "You can write list comprehensions across several lines. It's better to split longer list comprehensions across multiple\n",
    "lines, especially if they're nested.\n",
    "\n",
    "Tuples\n",
    "------\n",
    "\n",
    "<img src=\"img/tuple.png\" title=\"tuples\" style=\"background-color:white;float:right;margin-left:2em;\" />\n",
    "\n",
    "In some ways, tuples are like lists — they are a way to store several\n",
    "values into a single value. However, there are a few fundamental\n",
    "differences. A list of numbers is a list of numbers. That's its type and\n",
    "it doesn't matter if it has only one number in it or an infinite amount\n",
    "of numbers. Tuples, however, are used when you know exactly how many\n",
    "values you want to combine and its type depends on how many components\n",
    "it has and the types of the components. They are denoted with\n",
    "parentheses and their components are separated by commas.\n",
    "\n",
    "Another key difference is that they don't have to be homogenous. Unlike\n",
    "a list, a tuple can contain a combination of several types.\n",
    "\n",
    "Think about how we'd represent a two-dimensional vector in Haskell. One\n",
    "way would be to use a list. That would kind of work. So what if we\n",
    "wanted to put a couple of vectors in a list to represent points of a\n",
    "shape on a two-dimensional plane? We could do something like\n",
    "`[[1,2],[8,11],[4,5]]`. The problem with that method is that we could also\n",
    "do stuff like `[[1,2],[8,11,5],[4,5]]`, which Haskell has no problem with\n",
    "since it's still a list of lists with numbers but it kind of doesn't\n",
    "make sense. But a tuple of size two (also called a pair) is its own\n",
    "type, which means that a list can't have a couple of pairs in it and\n",
    "then a triple (a tuple of size three), so let's use that instead.\n",
    "Instead of surrounding the vectors with square brackets, we use\n",
    "parentheses: `[(1,2),(8,11),(4,5)]`. What if we tried to make a shape like\n",
    "`[(1,2),(8,11,5),(4,5)]`? Well, we'd get this error:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 102,
   "metadata": {
    "attributes": {
     "classes": [
      "haskell:",
      "ghci"
     ],
     "id": "",
     "name": "\"code\""
    }
   },
   "outputs": [
    {
     "ename": "",
     "evalue": "",
     "output_type": "error",
     "traceback": [
      "<interactive>:1:8: error:\n    • Couldn't match expected type: (a, b)\n                  with actual type: (a0, b0, c0)\n    • In the expression: (8, 11, 5)\n      In the expression: [(1, 2), (8, 11, 5), (4, 5)]\n      In an equation for ‘it’: it = [(1, 2), (8, 11, 5), (4, 5)]\n    • Relevant bindings include it :: [(a, b)] (bound at <interactive>:1:1)"
     ]
    }
   ],
   "source": [
    "[(1,2),(8,11,5),(4,5)]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "It's telling us that we tried to use a pair and a triple in the same\n",
    "list, which is not supposed to happen. You also couldn't make a list\n",
    "like `[(1,2),(\"One\",2)]` because the first element of the list is a pair\n",
    "of numbers and the second element is a pair consisting of a string and a\n",
    "number. Tuples can also be used to represent a wide variety of data. For\n",
    "instance, if we wanted to represent someone's name and age in Haskell,\n",
    "we could use a triple: `(\"Christopher\", \"Walken\", 55)`. As seen in this\n",
    "example, tuples can also contain lists.\n",
    "\n",
    "Use tuples when you know in advance how many components some piece of\n",
    "data should have. Tuples are much more rigid because each different size\n",
    "of tuple is its own type, so you can't write a general function to\n",
    "append an element to a tuple — you'd have to write a function for\n",
    "appending to a pair, one function for appending to a triple, one\n",
    "function for appending to a 4-tuple, etc.\n",
    "\n",
    "While there are singleton lists, there's no such thing as a singleton\n",
    "tuple. It doesn't really make much sense when you think about it. A\n",
    "singleton tuple would just be the value it contains and as such would\n",
    "have no benefit to us.\n",
    "\n",
    "Like lists, tuples can be compared with each other if their components\n",
    "can be compared. Only you can't compare two tuples of different sizes,\n",
    "whereas you can compare two lists of different sizes. Two useful\n",
    "functions that operate on pairs:\n",
    "\n",
    "__[`fst`](https://hackage.haskell.org/package/base/docs/Prelude.html#v:fst)__ takes a pair and returns its first component."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 103,
   "metadata": {
    "attributes": {
     "classes": [
      "haskell:",
      "ghci"
     ],
     "id": "",
     "name": "\"code\""
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "8"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "fst (8,11)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 104,
   "metadata": {
    "attributes": {
     "classes": [
      "haskell:",
      "ghci"
     ],
     "id": "",
     "name": "\"code\""
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "\"Wow\""
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "fst (\"Wow\", False)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "__[`snd`](https://hackage.haskell.org/package/base/docs/Prelude.html#v:snd)__ takes a pair and returns its second component. Surprise!"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 105,
   "metadata": {
    "attributes": {
     "classes": [
      "haskell:",
      "ghci"
     ],
     "id": "",
     "name": "\"code\""
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "11"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "snd (8,11)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 106,
   "metadata": {
    "attributes": {
     "classes": [
      "haskell:",
      "ghci"
     ],
     "id": "",
     "name": "\"code\""
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "False"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "snd (\"Wow\", False)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "> __Note:__ these functions operate only on pairs. They won't work on\n",
    "> triples, 4-tuples, 5-tuples, etc. We'll go over extracting data from\n",
    "> tuples in different ways a bit later.\n",
    "\n",
    "A cool function that produces a list of pairs: __[`zip`](https://hackage.haskell.org/package/base/docs/Prelude.html#v:zip)__. It takes two lists\n",
    "and then zips them together into one list by joining the matching\n",
    "elements into pairs. It's a really simple function but it has loads of\n",
    "uses. It's especially useful for when you want to combine two lists in a\n",
    "way or traverse two lists simultaneously. Here's a demonstration."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 107,
   "metadata": {
    "attributes": {
     "classes": [
      "haskell:",
      "ghci"
     ],
     "id": "",
     "name": "\"code\""
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[(1,5),(2,5),(3,5),(4,5),(5,5)]"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "zip [1,2,3,4,5] [5,5,5,5,5]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 108,
   "metadata": {
    "attributes": {
     "classes": [
      "haskell:",
      "ghci"
     ],
     "id": "",
     "name": "\"code\""
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[(1,\"one\"),(2,\"two\"),(3,\"three\"),(4,\"four\"),(5,\"five\")]"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "zip [1 .. 5] [\"one\", \"two\", \"three\", \"four\", \"five\"]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "It pairs up the elements and produces a new list. The first element goes\n",
    "with the first, the second with the second, etc. Notice that because\n",
    "pairs can have different types in them, [`zip`](https://hackage.haskell.org/package/base/docs/Prelude.html#v:zip) can take two lists that\n",
    "contain different types and zip them up. What happens if the lengths of\n",
    "the lists don't match?"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 109,
   "metadata": {
    "attributes": {
     "classes": [
      "haskell:",
      "ghci"
     ],
     "id": "",
     "name": "\"code\""
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[(5,\"im\"),(3,\"a\"),(2,\"turtle\")]"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "zip [5,3,2,6,2,7,2,5,4,6,6] [\"im\",\"a\",\"turtle\"]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The longer list simply gets cut off to match the length of the shorter\n",
    "one. Because Haskell is lazy, we can zip finite lists with infinite\n",
    "lists:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 110,
   "metadata": {
    "attributes": {
     "classes": [
      "haskell:",
      "ghci"
     ],
     "id": "",
     "name": "\"code\""
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[(1,\"apple\"),(2,\"orange\"),(3,\"cherry\"),(4,\"mango\")]"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "zip [1..] [\"apple\", \"orange\", \"cherry\", \"mango\"]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<img src=\"img/pythag.png\" title=\"look at meee\" style=\"background-color:white;margin-left:auto;margin-right:auto;\" />\n",
    "\n",
    "Here's a problem that combines tuples and list comprehensions: which\n",
    "right triangle that has integers for all sides and all sides equal to or\n",
    "smaller than 10 has a perimeter of 24? First, let's try generating all\n",
    "triangles with sides equal to or smaller than 10:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 111,
   "metadata": {
    "attributes": {
     "classes": [
      "haskell:",
      "ghci"
     ],
     "id": "",
     "name": "\"code\""
    }
   },
   "outputs": [],
   "source": [
    "let triangles = [ (a,b,c) | c <- [1..10], b <- [1..10], a <- [1..10] ]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We're just drawing from three lists and our output function is combining\n",
    "them into a triple. If you evaluate that by typing out `triangles` in\n",
    "GHC, you'll get a list of all possible triangles with sides under or\n",
    "equal to 10. Next, we'll add a condition that they all have to be right\n",
    "triangles. We'll also modify this function by taking into consideration\n",
    "that side b isn't larger than the hypotenuse and that side a isn't\n",
    "larger than side b."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 112,
   "metadata": {
    "attributes": {
     "classes": [
      "haskell:",
      "ghci"
     ],
     "id": "",
     "name": "\"code\""
    }
   },
   "outputs": [],
   "source": [
    "let rightTriangles = [ (a,b,c) | c <- [1..10], b <- [1..c], a <- [1..b], a^2 + b^2 == c^2]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We're almost done. Now, we just modify the function by saying that we\n",
    "want the ones where the perimeter is 24."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 113,
   "metadata": {
    "attributes": {
     "classes": [
      "haskell:",
      "ghci"
     ],
     "id": "",
     "name": "\"code\""
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[(6,8,10)]"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "let rightTriangles' = [ (a,b,c) | c <- [1..10], b <- [1..c], a <- [1..b], a^2 + b^2 == c^2, a+b+c == 24]\n",
    "rightTriangles'"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "And there's our answer! This is a common pattern in functional\n",
    "programming. You take a starting set of solutions and then you apply\n",
    "transformations to those solutions and filter them until you get the\n",
    "right ones."
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Haskell",
   "language": "haskell",
   "name": "haskell"
  },
  "language_info": {
   "codemirror_mode": "ihaskell",
   "file_extension": ".hs",
   "mimetype": "text/x-haskell",
   "name": "haskell",
   "pygments_lexer": "Haskell",
   "version": "9.2.5"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}


================================================
FILE: notebook/03-types-and-typeclasses.ipynb
================================================
{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Types and Typeclasses\n",
    "=====================\n",
    "\n",
    "Believe the type\n",
    "----------------\n",
    "\n",
    "<img src=\"img/cow.png\" title=\"moo\" style=\"background-color:white;float:left;margin-right:2em;\" />\n",
    "\n",
    "Previously we mentioned that Haskell has a static type system. The type\n",
    "of every expression is known at compile time, which leads to safer code.\n",
    "If you write a program where you try to divide a boolean type with some\n",
    "number, it won't even compile. That's good because it's better to catch\n",
    "such errors at compile time instead of having your program crash.\n",
    "Everything in Haskell has a type, so the compiler can reason quite a lot\n",
    "about your program before compiling it.\n",
    "\n",
    "Unlike Java or Pascal, Haskell has type inference. If we write a number,\n",
    "we don't have to tell Haskell it's a number. It can *infer* that on its\n",
    "own, so we don't have to explicitly write out the types of our functions\n",
    "and expressions to get things done. We covered some of the basics of\n",
    "Haskell with only a very superficial glance at types. However,\n",
    "understanding the type system is a very important part of learning\n",
    "Haskell.\n",
    "\n",
    "A type is a kind of label that every expression has. It tells us in\n",
    "which category of things that expression fits. The expression [`True`](https://hackage.haskell.org/package/base/docs/Prelude.html#v:True) is a\n",
    "boolean, `\"hello\"` is a string, etc."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "> __Jupyter Note:__ We'll turn off the [automatic linting for IHaskell](https://github.com/IHaskell/IHaskell/wiki#opt-no-lint) first."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    ":opt no-lint"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Now we'll use GHCI to examine the types of some expressions. We'll do\n",
    "that by using the `:t` command which, followed by any valid expression,\n",
    "tells us its type. Let's give it a whirl."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {
    "attributes": {
     "classes": [
      "haskell:",
      "ghci"
     ],
     "id": "",
     "name": "\"code\""
    }
   },
   "outputs": [
    {
     "data": {
      "text/html": [
       "<style>/* Styles used for the Hoogle display in the pager */\n",
       ".hoogle-doc {\n",
       "display: block;\n",
       "padding-bottom: 1.3em;\n",
       "padding-left: 0.4em;\n",
       "}\n",
       ".hoogle-code {\n",
       "display: block;\n",
       "font-family: monospace;\n",
       "white-space: pre;\n",
       "}\n",
       ".hoogle-text {\n",
       "display: block;\n",
       "}\n",
       ".hoogle-name {\n",
       "color: green;\n",
       "font-weight: bold;\n",
       "}\n",
       ".hoogle-head {\n",
       "font-weight: bold;\n",
       "}\n",
       ".hoogle-sub {\n",
       "display: block;\n",
       "margin-left: 0.4em;\n",
       "}\n",
       ".hoogle-package {\n",
       "font-weight: bold;\n",
       "font-style: italic;\n",
       "}\n",
       ".hoogle-module {\n",
       "font-weight: bold;\n",
       "}\n",
       ".hoogle-class {\n",
       "font-weight: bold;\n",
       "}\n",
       ".get-type {\n",
       "color: green;\n",
       "font-weight: bold;\n",
       "font-family: monospace;\n",
       "display: block;\n",
       "white-space: pre-wrap;\n",
       "}\n",
       ".show-type {\n",
       "color: green;\n",
       "font-weight: bold;\n",
       "font-family: monospace;\n",
       "margin-left: 1em;\n",
       "}\n",
       ".mono {\n",
       "font-family: monospace;\n",
       "display: block;\n",
       "}\n",
       ".err-msg {\n",
       "color: red;\n",
       "font-style: italic;\n",
       "font-family: monospace;\n",
       "white-space: pre;\n",
       "display: block;\n",
       "}\n",
       "#unshowable {\n",
       "color: red;\n",
       "font-weight: bold;\n",
       "}\n",
       ".err-msg.in.collapse {\n",
       "padding-top: 0.7em;\n",
       "}\n",
       ".highlight-code {\n",
       "white-space: pre;\n",
       "font-family: monospace;\n",
       "}\n",
       ".suggestion-warning { \n",
       "font-weight: bold;\n",
       "color: rgb(200, 130, 0);\n",
       "}\n",
       ".suggestion-error { \n",
       "font-weight: bold;\n",
       "color: red;\n",
       "}\n",
       ".suggestion-name {\n",
       "font-weight: bold;\n",
       "}\n",
       "</style><span class='get-type'>'a' :: Char</span>"
      ],
      "text/plain": [
       "'a' :: Char"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    ":t 'a'"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {
    "attributes": {
     "classes": [
      "haskell:",
      "ghci"
     ],
     "id": "",
     "name": "\"code\""
    }
   },
   "outputs": [
    {
     "data": {
      "text/html": [
       "<style>/* Styles used for the Hoogle display in the pager */\n",
       ".hoogle-doc {\n",
       "display: block;\n",
       "padding-bottom: 1.3em;\n",
       "padding-left: 0.4em;\n",
       "}\n",
       ".hoogle-code {\n",
       "display: block;\n",
       "font-family: monospace;\n",
       "white-space: pre;\n",
       "}\n",
       ".hoogle-text {\n",
       "display: block;\n",
       "}\n",
       ".hoogle-name {\n",
       "color: green;\n",
       "font-weight: bold;\n",
       "}\n",
       ".hoogle-head {\n",
       "font-weight: bold;\n",
       "}\n",
       ".hoogle-sub {\n",
       "display: block;\n",
       "margin-left: 0.4em;\n",
       "}\n",
       ".hoogle-package {\n",
       "font-weight: bold;\n",
       "font-style: italic;\n",
       "}\n",
       ".hoogle-module {\n",
       "font-weight: bold;\n",
       "}\n",
       ".hoogle-class {\n",
       "font-weight: bold;\n",
       "}\n",
       ".get-type {\n",
       "color: green;\n",
       "font-weight: bold;\n",
       "font-family: monospace;\n",
       "display: block;\n",
       "white-space: pre-wrap;\n",
       "}\n",
       ".show-type {\n",
       "color: green;\n",
       "font-weight: bold;\n",
       "font-family: monospace;\n",
       "margin-left: 1em;\n",
       "}\n",
       ".mono {\n",
       "font-family: monospace;\n",
       "display: block;\n",
       "}\n",
       ".err-msg {\n",
       "color: red;\n",
       "font-style: italic;\n",
       "font-family: monospace;\n",
       "white-space: pre;\n",
       "display: block;\n",
       "}\n",
       "#unshowable {\n",
       "color: red;\n",
       "font-weight: bold;\n",
       "}\n",
       ".err-msg.in.collapse {\n",
       "padding-top: 0.7em;\n",
       "}\n",
       ".highlight-code {\n",
       "white-space: pre;\n",
       "font-family: monospace;\n",
       "}\n",
       ".suggestion-warning { \n",
       "font-weight: bold;\n",
       "color: rgb(200, 130, 0);\n",
       "}\n",
       ".suggestion-error { \n",
       "font-weight: bold;\n",
       "color: red;\n",
       "}\n",
       ".suggestion-name {\n",
       "font-weight: bold;\n",
       "}\n",
       "</style><span class='get-type'>True :: Bool</span>"
      ],
      "text/plain": [
       "True :: Bool"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    ":t True"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {
    "attributes": {
     "classes": [
      "haskell:",
      "ghci"
     ],
     "id": "",
     "name": "\"code\""
    }
   },
   "outputs": [
    {
     "data": {
      "text/html": [
       "<style>/* Styles used for the Hoogle display in the pager */\n",
       ".hoogle-doc {\n",
       "display: block;\n",
       "padding-bottom: 1.3em;\n",
       "padding-left: 0.4em;\n",
       "}\n",
       ".hoogle-code {\n",
       "display: block;\n",
       "font-family: monospace;\n",
       "white-space: pre;\n",
       "}\n",
       ".hoogle-text {\n",
       "display: block;\n",
       "}\n",
       ".hoogle-name {\n",
       "color: green;\n",
       "font-weight: bold;\n",
       "}\n",
       ".hoogle-head {\n",
       "font-weight: bold;\n",
       "}\n",
       ".hoogle-sub {\n",
       "display: block;\n",
       "margin-left: 0.4em;\n",
       "}\n",
       ".hoogle-package {\n",
       "font-weight: bold;\n",
       "font-style: italic;\n",
       "}\n",
       ".hoogle-module {\n",
       "font-weight: bold;\n",
       "}\n",
       ".hoogle-class {\n",
       "font-weight: bold;\n",
       "}\n",
       ".get-type {\n",
       "color: green;\n",
       "font-weight: bold;\n",
       "font-family: monospace;\n",
       "display: block;\n",
       "white-space: pre-wrap;\n",
       "}\n",
       ".show-type {\n",
       "color: green;\n",
       "font-weight: bold;\n",
       "font-family: monospace;\n",
       "margin-left: 1em;\n",
       "}\n",
       ".mono {\n",
       "font-family: monospace;\n",
       "display: block;\n",
       "}\n",
       ".err-msg {\n",
       "color: red;\n",
       "font-style: italic;\n",
       "font-family: monospace;\n",
       "white-space: pre;\n",
       "display: block;\n",
       "}\n",
       "#unshowable {\n",
       "color: red;\n",
       "font-weight: bold;\n",
       "}\n",
       ".err-msg.in.collapse {\n",
       "padding-top: 0.7em;\n",
       "}\n",
       ".highlight-code {\n",
       "white-space: pre;\n",
       "font-family: monospace;\n",
       "}\n",
       ".suggestion-warning { \n",
       "font-weight: bold;\n",
       "color: rgb(200, 130, 0);\n",
       "}\n",
       ".suggestion-error { \n",
       "font-weight: bold;\n",
       "color: red;\n",
       "}\n",
       ".suggestion-name {\n",
       "font-weight: bold;\n",
       "}\n",
       "</style><span class='get-type'>\"HELLO!\" :: String</span>"
      ],
      "text/plain": [
       "\"HELLO!\" :: String"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    ":t \"HELLO!\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {
    "attributes": {
     "classes": [
      "haskell:",
      "ghci"
     ],
     "id": "",
     "name": "\"code\""
    }
   },
   "outputs": [
    {
     "data": {
      "text/html": [
       "<style>/* Styles used for the Hoogle display in the pager */\n",
       ".hoogle-doc {\n",
       "display: block;\n",
       "padding-bottom: 1.3em;\n",
       "padding-left: 0.4em;\n",
       "}\n",
       ".hoogle-code {\n",
       "display: block;\n",
       "font-family: monospace;\n",
       "white-space: pre;\n",
       "}\n",
       ".hoogle-text {\n",
       "display: block;\n",
       "}\n",
       ".hoogle-name {\n",
       "color: green;\n",
       "font-weight: bold;\n",
       "}\n",
       ".hoogle-head {\n",
       "font-weight: bold;\n",
       "}\n",
       ".hoogle-sub {\n",
       "display: block;\n",
       "margin-left: 0.4em;\n",
       "}\n",
       ".hoogle-package {\n",
       "font-weight: bold;\n",
       "font-style: italic;\n",
       "}\n",
       ".hoogle-module {\n",
       "font-weight: bold;\n",
       "}\n",
       ".hoogle-class {\n",
       "font-weight: bold;\n",
       "}\n",
       ".get-type {\n",
       "color: green;\n",
       "font-weight: bold;\n",
       "font-family: monospace;\n",
       "display: block;\n",
       "white-space: pre-wrap;\n",
       "}\n",
       ".show-type {\n",
       "color: green;\n",
       "font-weight: bold;\n",
       "font-family: monospace;\n",
       "margin-left: 1em;\n",
       "}\n",
       ".mono {\n",
       "font-family: monospace;\n",
       "display: block;\n",
       "}\n",
       ".err-msg {\n",
       "color: red;\n",
       "font-style: italic;\n",
       "font-family: monospace;\n",
       "white-space: pre;\n",
       "display: block;\n",
       "}\n",
       "#unshowable {\n",
       "color: red;\n",
       "font-weight: bold;\n",
       "}\n",
       ".err-msg.in.collapse {\n",
       "padding-top: 0.7em;\n",
       "}\n",
       ".highlight-code {\n",
       "white-space: pre;\n",
       "font-family: monospace;\n",
       "}\n",
       ".suggestion-warning { \n",
       "font-weight: bold;\n",
       "color: rgb(200, 130, 0);\n",
       "}\n",
       ".suggestion-error { \n",
       "font-weight: bold;\n",
       "color: red;\n",
       "}\n",
       ".suggestion-name {\n",
       "font-weight: bold;\n",
       "}\n",
       "</style><span class='get-type'>(True, 'a') :: (Bool, Char)</span>"
      ],
      "text/plain": [
       "(True, 'a') :: (Bool, Char)"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    ":t (True, 'a')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {
    "attributes": {
     "classes": [
      "haskell:",
      "ghci"
     ],
     "id": "",
     "name": "\"code\""
    }
   },
   "outputs": [
    {
     "data": {
      "text/html": [
       "<style>/* Styles used for the Hoogle display in the pager */\n",
       ".hoogle-doc {\n",
       "display: block;\n",
       "padding-bottom: 1.3em;\n",
       "padding-left: 0.4em;\n",
       "}\n",
       ".hoogle-code {\n",
       "display: block;\n",
       "font-family: monospace;\n",
       "white-space: pre;\n",
       "}\n",
       ".hoogle-text {\n",
       "display: block;\n",
       "}\n",
       ".hoogle-name {\n",
       "color: green;\n",
       "font-weight: bold;\n",
       "}\n",
       ".hoogle-head {\n",
       "font-weight: bold;\n",
       "}\n",
       ".hoogle-sub {\n",
       "display: block;\n",
       "margin-left: 0.4em;\n",
       "}\n",
       ".hoogle-package {\n",
       "font-weight: bold;\n",
       "font-style: italic;\n",
       "}\n",
       ".hoogle-module {\n",
       "font-weight: bold;\n",
       "}\n",
       ".hoogle-class {\n",
       "font-weight: bold;\n",
       "}\n",
       ".get-type {\n",
       "color: green;\n",
       "font-weight: bold;\n",
       "font-family: monospace;\n",
       "display: block;\n",
       "white-space: pre-wrap;\n",
       "}\n",
       ".show-type {\n",
       "color: green;\n",
       "font-weight: bold;\n",
       "font-family: monospace;\n",
       "margin-left: 1em;\n",
       "}\n",
       ".mono {\n",
       "font-family: monospace;\n",
       "display: block;\n",
       "}\n",
       ".err-msg {\n",
       "color: red;\n",
       "font-style: italic;\n",
       "font-family: monospace;\n",
       "white-space: pre;\n",
       "display: block;\n",
       "}\n",
       "#unshowable {\n",
       "color: red;\n",
       "font-weight: bold;\n",
       "}\n",
       ".err-msg.in.collapse {\n",
       "padding-top: 0.7em;\n",
       "}\n",
       ".highlight-code {\n",
       "white-space: pre;\n",
       "font-family: monospace;\n",
       "}\n",
       ".suggestion-warning { \n",
       "font-weight: bold;\n",
       "color: rgb(200, 130, 0);\n",
       "}\n",
       ".suggestion-error { \n",
       "font-weight: bold;\n",
       "color: red;\n",
       "}\n",
       ".suggestion-name {\n",
       "font-weight: bold;\n",
       "}\n",
       "</style><span class='get-type'>4 == 5 :: Bool</span>"
      ],
      "text/plain": [
       "4 == 5 :: Bool"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    ":t 4 == 5"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<img src=\"img/bomb.png\" title=\"bomb\" style=\"background-color:white;float:right;margin-left:2em;\" /> Here we see that doing `:t`\n",
    "on an expression prints out the expression followed by `::` and its type.\n",
    "`::` is read as \"has type of\". Explicit types are always denoted with the\n",
    "first letter in capital case. `'a'`, as it would seem, has a type of [`Char`](https://hackage.haskell.org/package/base/docs/Prelude.html#t:Char).\n",
    "It's not hard to conclude that it stands for *character*. [`True`](https://hackage.haskell.org/package/base/docs/Prelude.html#v:True) is of a\n",
    "[`Bool`](https://hackage.haskell.org/package/base/docs/Prelude.html#t:Bool) type. That makes sense. But what's this? Examining the type of\n",
    "`\"HELLO!\"` yields a `[Char]`. The square brackets denote a list. So we read\n",
    "that as it being *a list of characters*. Unlike lists, each tuple length\n",
    "has its own type. So the expression of `(True, 'a')` has a type of\n",
    "`(Bool, Char)`, whereas an expression such as `('a','b','c')` would have the\n",
    "type of `(Char, Char, Char)`. `4 == 5` will always return [`False`](https://hackage.haskell.org/package/base/docs/Prelude.html#v:False), so its type\n",
    "is [`Bool`](https://hackage.haskell.org/package/base/docs/Prelude.html#t:Bool).\n",
    "\n",
    "Functions also have types. When writing our own functions, we can choose\n",
    "to give them an explicit type declaration. This is generally considered\n",
    "to be good practice except when writing very short functions. From here\n",
    "on, we'll give all the functions that we make type declarations.\n",
    "Remember the list comprehension we made previously that filters a string\n",
    "so that only caps remain? Here's how it looks like with a type\n",
    "declaration."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {
    "attributes": {
     "classes": [
      "haskell:",
      "hs"
     ],
     "id": "",
     "name": "\"code\""
    }
   },
   "outputs": [],
   "source": [
    "removeNonUppercase :: [Char] -> [Char]\n",
    "removeNonUppercase st = [ c | c <- st, c `elem` ['A'..'Z']]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "`removeNonUppercase` has a type of `[Char] -> [Char]`, meaning that it maps\n",
    "from a string to a string. That's because it takes one string as a\n",
    "parameter and returns another as a result. The `[Char]` type is synonymous\n",
    "with [`String`](https://hackage.haskell.org/package/base/docs/Prelude.html#t:String) so it's clearer if we write\n",
    "`removeNonUppercase :: String -> String`.\n",
    "We didn't have to give this function a type declaration because\n",
    "the compiler can infer by itself that it's a function from a string to a\n",
    "string but we did anyway. But how do we write out the type of a function\n",
    "that takes several parameters? Here's a simple function that takes three\n",
    "integers and adds them together:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {
    "attributes": {
     "classes": [
      "haskell:",
      "hs"
     ],
     "id": "",
     "name": "\"code\""
    }
   },
   "outputs": [],
   "source": [
    "addThree :: Int -> Int -> Int -> Int\n",
    "addThree x y z = x + y + z"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The parameters are separated with `->` and there's no special distinction\n",
    "between the parameters and the return type. The return type is the last\n",
    "item in the declaration and the parameters are the first three. Later on\n",
    "we'll see why they're all just separated with `->` instead of having some\n",
    "more explicit distinction between the return types and the parameters\n",
    "like `Int, Int, Int -> Int` or something.\n",
    "\n",
    "If you want to give your function a type declaration but are unsure as\n",
    "to what it should be, you can always just write the function without it\n",
    "and then check it with `:t`. Functions are expressions too, so `:t` works\n",
    "on them without a problem.\n",
    "\n",
    "Here's an overview of some common types.\n",
    "\n",
    "__[`Int`](https://hackage.haskell.org/package/base/docs/Prelude.html#t:Int)__ stands for integer. It's used for whole numbers. `7` can be an [`Int`](https://hackage.haskell.org/package/base/docs/Prelude.html#t:Int) but\n",
    "`7.2` cannot. [`Int`](https://hackage.haskell.org/package/base/docs/Prelude.html#t:Int) is bounded, which means that it has a minimum and a\n",
    "maximum value. Usually on 32-bit machines the maximum possible [`Int`](https://hackage.haskell.org/package/base/docs/Prelude.html#t:Int) is\n",
    "2147483647 and the minimum is -2147483648.\n",
    "\n",
    "__[`Integer`](https://hackage.haskell.org/package/base/docs/Prelude.html#t:Integer)__ stands for, er … also integer. The main difference is that it's\n",
    "not bounded so it can be used to represent really really big numbers. I\n",
    "mean like really big. [`Int`](https://hackage.haskell.org/package/base/docs/Prelude.html#t:Int), however, is more efficient."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {
    "attributes": {
     "classes": [
      "haskell:",
      "hs"
     ],
     "id": "",
     "name": "\"code\""
    }
   },
   "outputs": [],
   "source": [
    "factorial :: Integer -> Integer\n",
    "factorial n = product [1..n]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {
    "attributes": {
     "classes": [
      "haskell:",
      "ghci"
     ],
     "id": "",
     "name": "\"code\""
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "30414093201713378043612608166064768844377641568960512000000000000"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "factorial 50"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "__[`Float`](https://hackage.haskell.org/package/base/docs/Prelude.html#t:Float)__ is a real floating point with single precision."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {
    "attributes": {
     "classes": [
      "haskell:",
      "hs"
     ],
     "id": "",
     "name": "\"code\""
    }
   },
   "outputs": [],
   "source": [
    "circumference :: Float -> Float\n",
    "circumference r = 2 * pi * r"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {
    "attributes": {
     "classes": [
      "haskell:",
      "ghci"
     ],
     "id": "",
     "name": "\"code\""
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "25.132742"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "circumference 4.0"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "__[`Double`](https://hackage.haskell.org/package/base/docs/Prelude.html#t:Double)__ is a real floating point with double the precision!"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {
    "attributes": {
     "classes": [
      "haskell:",
      "hs"
     ],
     "id": "",
     "name": "\"code\""
    }
   },
   "outputs": [],
   "source": [
    "circumference' :: Double -> Double\n",
    "circumference' r = 2 * pi * r"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {
    "attributes": {
     "classes": [
      "haskell:",
      "ghci"
     ],
     "id": "",
     "name": "\"code\""
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "25.132741228718345"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "circumference' 4.0"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "__[`Bool`](https://hackage.haskell.org/package/base/docs/Prelude.html#t:Bool)__ is a boolean type. It can have only two values: [`True`](https://hackage.haskell.org/package/base/docs/Prelude.html#v:True) and [`False`](https://hackage.haskell.org/package/base/docs/Prelude.html#v:False).\n",
    "\n",
    "__[`Char`](https://hackage.haskell.org/package/base/docs/Prelude.html#t:Char)__ represents a character. It's denoted by single quotes. A list of\n",
    "characters is a string.\n",
    "\n",
    "Tuples are types but they are dependent on their length as well as the\n",
    "types of their components, so there is theoretically an infinite number\n",
    "of tuple types, which is too many to cover in this tutorial. Note that\n",
    "the empty tuple `()` is also a type which can only have a single value: `()`\n",
    "\n",
    "Type variables\n",
    "--------------\n",
    "\n",
    "What do you think is the type of the [`head`](https://hackage.haskell.org/package/base/docs/Prelude.html#v:head) function? Because [`head`](https://hackage.haskell.org/package/base/docs/Prelude.html#v:head) takes a\n",
    "list of any type and returns the first element, so what could it be?\n",
    "Let's check!"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {
    "attributes": {
     "classes": [
      "haskell:",
      "ghci"
     ],
     "id": "",
     "name": "\"code\""
    }
   },
   "outputs": [
    {
     "data": {
      "text/html": [
       "<style>/* Styles used for the Hoogle display in the pager */\n",
       ".hoogle-doc {\n",
       "display: block;\n",
       "padding-bottom: 1.3em;\n",
       "padding-left: 0.4em;\n",
       "}\n",
       ".hoogle-code {\n",
       "display: block;\n",
       "font-family: monospace;\n",
       "white-space: pre;\n",
       "}\n",
       ".hoogle-text {\n",
       "display: block;\n",
       "}\n",
       ".hoogle-name {\n",
       "color: green;\n",
       "font-weight: bold;\n",
       "}\n",
       ".hoogle-head {\n",
       "font-weight: bold;\n",
       "}\n",
       ".hoogle-sub {\n",
       "display: block;\n",
       "margin-left: 0.4em;\n",
       "}\n",
       ".hoogle-package {\n",
       "font-weight: bold;\n",
       "font-style: italic;\n",
       "}\n",
       ".hoogle-module {\n",
       "font-weight: bold;\n",
       "}\n",
       ".hoogle-class {\n",
       "font-weight: bold;\n",
       "}\n",
       ".get-type {\n",
       "color: green;\n",
       "font-weight: bold;\n",
       "font-family: monospace;\n",
       "display: block;\n",
       "white-space: pre-wrap;\n",
       "}\n",
       ".show-type {\n",
       "color: green;\n",
       "font-weight: bold;\n",
       "font-family: monospace;\n",
       "margin-left: 1em;\n",
       "}\n",
       ".mono {\n",
       "font-family: monospace;\n",
       "display: block;\n",
       "}\n",
       ".err-msg {\n",
       "color: red;\n",
       "font-style: italic;\n",
       "font-family: monospace;\n",
       "white-space: pre;\n",
       "display: block;\n",
       "}\n",
       "#unshowable {\n",
       "color: red;\n",
       "font-weight: bold;\n",
       "}\n",
       ".err-msg.in.collapse {\n",
       "padding-top: 0.7em;\n",
       "}\n",
       ".highlight-code {\n",
       "white-space: pre;\n",
       "font-family: monospace;\n",
       "}\n",
       ".suggestion-warning { \n",
       "font-weight: bold;\n",
       "color: rgb(200, 130, 0);\n",
       "}\n",
       ".suggestion-error { \n",
       "font-weight: bold;\n",
       "color: red;\n",
       "}\n",
       ".suggestion-name {\n",
       "font-weight: bold;\n",
       "}\n",
       "</style><span class='get-type'>head :: forall a. [a] -> a</span>"
      ],
      "text/plain": [
       "head :: forall a. [a] -> a"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    ":t head"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<img src=\"img/box.png\" title=\"box\" style=\"background-color:white;float:left;margin-right:2em;\" /> Hmmm! What is this `a`? Is it\n",
    "a type? Remember that we previously stated that types are written in\n",
    "capital case, so it can't exactly be a type. Because it's not in capital\n",
    "case it's actually a *type variable*. That means that `a` can be of any\n",
    "type. This is much like generics in other languages, only in Haskell\n",
    "it's much more powerful because it allows us to easily write very\n",
    "general functions if they don't use any specific behavior of the types\n",
    "in them. Functions that have type variables are called *polymorphic\n",
    "functions*. The type declaration of [`head`](https://hackage.haskell.org/package/base/docs/Prelude.html#v:head) states that it takes a list of\n",
    "any type and returns one element of that type.\n",
    "\n",
    "Although type variables can have names longer than one character, we\n",
    "usually give them names of a, b, c, d …\n",
    "\n",
    "Remember [`fst`](https://hackage.haskell.org/package/base/docs/Prelude.html#v:fst)? It returns the first component of a pair. Let's examine\n",
    "its type."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {
    "attributes": {
     "classes": [
      "haskell:",
      "ghci"
     ],
     "id": "",
     "name": "\"code\""
    }
   },
   "outputs": [
    {
     "data": {
      "text/html": [
       "<style>/* Styles used for the Hoogle display in the pager */\n",
       ".hoogle-doc {\n",
       "display: block;\n",
       "padding-bottom: 1.3em;\n",
       "padding-left: 0.4em;\n",
       "}\n",
       ".hoogle-code {\n",
       "display: block;\n",
       "font-family: monospace;\n",
       "white-space: pre;\n",
       "}\n",
       ".hoogle-text {\n",
       "display: block;\n",
       "}\n",
       ".hoogle-name {\n",
       "color: green;\n",
       "font-weight: bold;\n",
       "}\n",
       ".hoogle-head {\n",
       "font-weight: bold;\n",
       "}\n",
       ".hoogle-sub {\n",
       "display: block;\n",
       "margin-left: 0.4em;\n",
       "}\n",
       ".hoogle-package {\n",
       "font-weight: bold;\n",
       "font-style: italic;\n",
       "}\n",
       ".hoogle-module {\n",
       "font-weight: bold;\n",
       "}\n",
       ".hoogle-class {\n",
       "font-weight: bold;\n",
       "}\n",
       ".get-type {\n",
       "color: green;\n",
       "font-weight: bold;\n",
       "font-family: monospace;\n",
       "display: block;\n",
       "white-space: pre-wrap;\n",
       "}\n",
       ".show-type {\n",
       "color: green;\n",
       "font-weight: bold;\n",
       "font-family: monospace;\n",
       "margin-left: 1em;\n",
       "}\n",
       ".mono {\n",
       "font-family: monospace;\n",
       "display: block;\n",
       "}\n",
       ".err-msg {\n",
       "color: red;\n",
       "font-style: italic;\n",
       "font-family: monospace;\n",
       "white-space: pre;\n",
       "display: block;\n",
       "}\n",
       "#unshowable {\n",
       "color: red;\n",
       "font-weight: bold;\n",
       "}\n",
       ".err-msg.in.collapse {\n",
       "padding-top: 0.7em;\n",
       "}\n",
       ".highlight-code {\n",
       "white-space: pre;\n",
       "font-family: monospace;\n",
       "}\n",
       ".suggestion-warning { \n",
       "font-weight: bold;\n",
       "color: rgb(200, 130, 0);\n",
       "}\n",
       ".suggestion-error { \n",
       "font-weight: bold;\n",
       "color: red;\n",
       "}\n",
       ".suggestion-name {\n",
       "font-weight: bold;\n",
       "}\n",
       "</style><span class='get-type'>fst :: forall a b. (a, b) -> a</span>"
      ],
      "text/plain": [
       "fst :: forall a b. (a, b) -> a"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    ":t fst"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We see that [`fst`](https://hackage.haskell.org/package/base/docs/Prelude.html#v:fst) takes a tuple which contains two types and returns an\n",
    "element which is of the same type as the pair's first component. That's\n",
    "why we can use [`fst`](https://hackage.haskell.org/package/base/docs/Prelude.html#v:fst) on a pair that contains any two types. Note that just\n",
    "because `a` and `b` are different type variables, they don't have to be\n",
    "different types. It just states that the first component's type and the\n",
    "return value's type are the same.\n",
    "\n",
    "<a name=\"typeclasses-101\"></a>\n",
    "\n",
    "Typeclasses 101\n",
    "---------------\n",
    "\n",
    "<img src=\"img/classes.png\" title=\"class\" style=\"background-color:white;float:right;margin-left:2em;\" />\n",
    "\n",
    "A typeclass is a sort of interface that defines some behavior. If a type\n",
    "is a part of a typeclass, that means that it supports and implements the\n",
    "behavior the typeclass describes. A lot of people coming from OOP get\n",
    "confused by typeclasses because they think they are like classes in\n",
    "object oriented languages. Well, they're not. You can think of them kind\n",
    "of as Java interfaces, only better.\n",
    "\n",
    "What's the type signature of the [`==`](https://hackage.haskell.org/package/base/docs/Prelude.html#v:-61--61-) function?"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {
    "attributes": {
     "classes": [
      "haskell:",
      "ghci"
     ],
     "id": "",
     "name": "\"code\""
    }
   },
   "outputs": [
    {
     "data": {
      "text/html": [
       "<style>/* Styles used for the Hoogle display in the pager */\n",
       ".hoogle-doc {\n",
       "display: block;\n",
       "padding-bottom: 1.3em;\n",
       "padding-left: 0.4em;\n",
       "}\n",
       ".hoogle-code {\n",
       "display: block;\n",
       "font-family: monospace;\n",
       "white-space: pre;\n",
       "}\n",
       ".hoogle-text {\n",
       "display: block;\n",
       "}\n",
       ".hoogle-name {\n",
       "color: green;\n",
       "font-weight: bold;\n",
       "}\n",
       ".hoogle-head {\n",
       "font-weight: bold;\n",
       "}\n",
       ".hoogle-sub {\n",
       "display: block;\n",
       "margin-left: 0.4em;\n",
       "}\n",
       ".hoogle-package {\n",
       "font-weight: bold;\n",
       "font-style: italic;\n",
       "}\n",
       ".hoogle-module {\n",
       "font-weight: bold;\n",
       "}\n",
       ".hoogle-class {\n",
       "font-weight: bold;\n",
       "}\n",
       ".get-type {\n",
       "color: green;\n",
       "font-weight: bold;\n",
       "font-family: monospace;\n",
       "display: block;\n",
       "white-space: pre-wrap;\n",
       "}\n",
       ".show-type {\n",
       "color: green;\n",
       "font-weight: bold;\n",
       "font-family: monospace;\n",
       "margin-left: 1em;\n",
       "}\n",
       ".mono {\n",
       "font-family: monospace;\n",
       "display: block;\n",
       "}\n",
       ".err-msg {\n",
       "color: red;\n",
       "font-style: italic;\n",
       "font-family: monospace;\n",
       "white-space: pre;\n",
       "display: block;\n",
       "}\n",
       "#unshowable {\n",
       "color: red;\n",
       "font-weight: bold;\n",
       "}\n",
       ".err-msg.in.collapse {\n",
       "padding-top: 0.7em;\n",
       "}\n",
       ".highlight-code {\n",
       "white-space: pre;\n",
       "font-family: monospace;\n",
       "}\n",
       ".suggestion-warning { \n",
       "font-weight: bold;\n",
       "color: rgb(200, 130, 0);\n",
       "}\n",
       ".suggestion-error { \n",
       "font-weight: bold;\n",
       "color: red;\n",
       "}\n",
       ".suggestion-name {\n",
       "font-weight: bold;\n",
       "}\n",
       "</style><span class='get-type'>(==) :: forall a. Eq a => a -> a -> Bool</span>"
      ],
      "text/plain": [
       "(==) :: forall a. Eq a => a -> a -> Bool"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    ":t (==)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "> __Note__: the equality operator, [`==`](https://hackage.haskell.org/package/base/docs/Prelude.html#v:-61--61-) is a function. So are [`+`](https://hackage.haskell.org/package/base/docs/Prelude.html#v:-43-), [`*`](https://hackage.haskell.org/package/base/docs/Prelude.html#v:-42-), [`-`](https://hackage.haskell.org/package/base/docs/Prelude.html#v:-45-), [`/`](https://hackage.haskell.org/package/base/docs/Prelude.html#v:-47-) and\n",
    "> pretty much all operators. If a function is comprised only of special\n",
    "> characters, it's considered an infix function by default. If we want to\n",
    "> examine its type, pass it to another function or call it as a prefix\n",
    "> function, we have to surround it in parentheses.\n",
    "\n",
    "Interesting. We see a new thing here, the `=>` symbol. Everything before\n",
    "the `=>` symbol is called a *class constraint*. We can read the previous\n",
    "type declaration like this: the equality function takes any two values\n",
    "that are of the same type and returns a [`Bool`](https://hackage.haskell.org/package/base/docs/Prelude.html#t:Bool). The type of those two\n",
    "values must be a member of the `Eq` class (this was the class constraint).\n",
    "\n",
    "The `Eq` typeclass provides an interface for testing for equality. Any\n",
    "type where it makes sense to test for equality between two values of\n",
    "that type should be a member of the `Eq` class. All standard Haskell types\n",
    "except for [`IO`](https://hackage.haskell.org/package/base/docs/Prelude.html#t:IO) (the type for dealing with input and output) and functions\n",
    "are a part of the `Eq` typeclass.\n",
    "\n",
    "The [`elem`](https://hackage.haskell.org/package/base/docs/Prelude.html#v:elem) function has a type of `(Eq a) => a -> [a] -> Bool` because it\n",
    "uses [`==`](https://hackage.haskell.org/package/base/docs/Prelude.html#v:-61--61-) over a list to check whether some value we're looking for is in\n",
    "it.\n",
    "\n",
    "Some basic typeclasses:\n",
    "\n",
    "__`Eq`__ is used for types that support equality testing. The functions its\n",
    "members implement are [`==`](https://hackage.haskell.org/package/base/docs/Prelude.html#v:-61--61-) and [`/=`](https://hackage.haskell.org/package/base/docs/Prelude.html#v:-47--61-). So if there's an `Eq` class constraint\n",
    "for a type variable in a function, it uses [`==`](https://hackage.haskell.org/package/base/docs/Prelude.html#v:-61--61-) or [`/=`](https://hackage.haskell.org/package/base/docs/Prelude.html#v:-47--61-) somewhere inside its\n",
    "definition. All the types we mentioned previously except for functions\n",
    "are part of `Eq`, so they can be tested for equality."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {
    "attributes": {
     "classes": [
      "haskell:",
      "ghci"
     ],
     "id": "",
     "name": "\"code\""
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "True"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "5 == 5"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {
    "attributes": {
     "classes": [
      "haskell:",
      "ghci"
     ],
     "id": "",
     "name": "\"code\""
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "False"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "5 /= 5"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {
    "attributes": {
     "classes": [
      "haskell:",
      "ghci"
     ],
     "id": "",
     "name": "\"code\""
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "True"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "'a' == 'a'"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "metadata": {
    "attributes": {
     "classes": [
      "haskell:",
      "ghci"
     ],
     "id": "",
     "name": "\"code\""
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "True"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "\"Ho Ho\" == \"Ho Ho\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "metadata": {
    "attributes": {
     "classes": [
      "haskell:",
      "ghci"
     ],
     "id": "",
     "name": "\"code\""
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "True"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "3.432 == 3.432"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "__[`Ord`](https://hackage.haskell.org/package/base/docs/Prelude.html#t:Ord)__ is for types that have an ordering."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "metadata": {
    "attributes": {
     "classes": [
      "haskell:",
      "ghci"
     ],
     "id": "",
     "name": "\"code\""
    }
   },
   "outputs": [
    {
     "data": {
      "text/html": [
       "<style>/* Styles used for the Hoogle display in the pager */\n",
       ".hoogle-doc {\n",
       "display: block;\n",
       "padding-bottom: 1.3em;\n",
       "padding-left: 0.4em;\n",
       "}\n",
       ".hoogle-code {\n",
       "display: block;\n",
       "font-family: monospace;\n",
       "white-space: pre;\n",
       "}\n",
       ".hoogle-text {\n",
       "display: block;\n",
       "}\n",
       ".hoogle-name {\n",
       "color: green;\n",
       "font-weight: bold;\n",
       "}\n",
       ".hoogle-head {\n",
       "font-weight: bold;\n",
       "}\n",
       ".hoogle-sub {\n",
       "display: block;\n",
       "margin-left: 0.4em;\n",
       "}\n",
       ".hoogle-package {\n",
       "font-weight: bold;\n",
       "font-style: italic;\n",
       "}\n",
       ".hoogle-module {\n",
       "font-weight: bold;\n",
       "}\n",
       ".hoogle-class {\n",
       "font-weight: bold;\n",
       "}\n",
       ".get-type {\n",
       "color: green;\n",
       "font-weight: bold;\n",
       "font-family: monospace;\n",
       "display: block;\n",
       "white-space: pre-wrap;\n",
       "}\n",
       ".show-type {\n",
       "color: green;\n",
       "font-weight: bold;\n",
       "font-family: monospace;\n",
       "margin-left: 1em;\n",
       "}\n",
       ".mono {\n",
       "font-family: monospace;\n",
       "display: block;\n",
       "}\n",
       ".err-msg {\n",
       "color: red;\n",
       "font-style: italic;\n",
       "font-family: monospace;\n",
       "white-space: pre;\n",
       "display: block;\n",
       "}\n",
       "#unshowable {\n",
       "color: red;\n",
       "font-weight: bold;\n",
       "}\n",
       ".err-msg.in.collapse {\n",
       "padding-top: 0.7em;\n",
       "}\n",
       ".highlight-code {\n",
       "white-space: pre;\n",
       "font-family: monospace;\n",
       "}\n",
       ".suggestion-warning { \n",
       "font-weight: bold;\n",
       "color: rgb(200, 130, 0);\n",
       "}\n",
       ".suggestion-error { \n",
       "font-weight: bold;\n",
       "color: red;\n",
       "}\n",
       ".suggestion-name {\n",
       "font-weight: bold;\n",
       "}\n",
       "</style><span class='get-type'>(>) :: forall a. Ord a => a -> a -> Bool</span>"
      ],
      "text/plain": [
       "(>) :: forall a. Ord a => a -> a -> Bool"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    ":t (>)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "All the types we covered so far except for functions are part of [`Ord`](https://hackage.haskell.org/package/base/docs/Prelude.html#t:Ord).\n",
    "[`Ord`](https://hackage.haskell.org/package/base/docs/Prelude.html#t:Ord) covers all the standard comparing functions such as [`>`](https://hackage.haskell.org/package/base/docs/Prelude.html#v:-62-), [`<`](https://hackage.haskell.org/package/base/docs/Prelude.html#v:-60-), [`>=`](https://hackage.haskell.org/package/base/docs/Prelude.html#v:-62--61-) and\n",
    "[`<=`](https://hackage.haskell.org/package/base/docs/Prelude.html#v:-60--61-). The [`compare`](https://hackage.haskell.org/package/base/docs/Prelude.html#v:compare) function takes two [`Ord`](https://hackage.haskell.org/package/base/docs/Prelude.html#t:Ord) members of the same type and\n",
    "returns an ordering. [`Ordering`](https://hackage.haskell.org/package/base/docs/Prelude.html#t:Ordering) is a type that can be [`GT`](https://hackage.haskell.org/package/base/docs/Prelude.html#v:GT), [`LT`](https://hackage.haskell.org/package/base/docs/Prelude.html#v:LT) or [`EQ`](https://hackage.haskell.org/package/base/docs/Prelude.html#v:EQ),\n",
    "meaning *greater than*, *lesser than* and *equal*, respectively.\n",
    "\n",
    "To be a member of [`Ord`](https://hackage.haskell.org/package/base/docs/Prelude.html#t:Ord), a type must first have membership in the\n",
    "prestigious and exclusive `Eq` club."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "metadata": {
    "attributes": {
     "classes": [
      "haskell:",
      "ghci"
     ],
     "id": "",
     "name": "\"code\""
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "True"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "\"Abrakadabra\" < \"Zebra\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "metadata": {
    "attributes": {
     "classes": [
      "haskell:",
      "ghci"
     ],
     "id": "",
     "name": "\"code\""
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "LT"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "\"Abrakadabra\" `compare` \"Zebra\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "metadata": {
    "attributes": {
     "classes": [
      "haskell:",
      "ghci"
     ],
     "id": "",
     "name": "\"code\""
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "True"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "5 >= 2"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "metadata": {
    "attributes": {
     "classes": [
      "haskell:",
      "ghci"
     ],
     "id": "",
     "name": "\"code\""
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "GT"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "5 `compare` 3"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Members of __[`Show`](https://hackage.haskell.org/package/base/docs/Prelude.html#t:Show)__ can be presented as strings. All types covered so far\n",
    "except for functions are a part of [`Show`](https://hackage.haskell.org/package/base/docs/Prelude.html#t:Show). The most used function that\n",
    "deals with the [`Show`](https://hackage.haskell.org/package/base/docs/Prelude.html#t:Show) typeclass is show. It takes a value whose type is a\n",
    "member of [`Show`](https://hackage.haskell.org/package/base/docs/Prelude.html#t:Show) and presents it to us as a string."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "metadata": {
    "attributes": {
     "classes": [
      "haskell:",
      "ghci"
     ],
     "id": "",
     "name": "\"code\""
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "\"3\""
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "show 3"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "metadata": {
    "attributes": {
     "classes": [
      "haskell:",
      "ghci"
     ],
     "id": "",
     "name": "\"code\""
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "\"5.334\""
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "show 5.334"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 30,
   "metadata": {
    "attributes": {
     "classes": [
      "haskell:",
      "ghci"
     ],
     "id": "",
     "name": "\"code\""
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "\"True\""
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "show True"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "__[`Read`](https://hackage.haskell.org/package/base/docs/Prelude.html#t:Read)__ is sort of the opposite typeclass of [`Show`](https://hackage.haskell.org/package/base/docs/Prelude.html#t:Show). The [`read`](https://hackage.haskell.org/package/base/docs/Prelude.html#v:read) function takes\n",
    "a string and returns a type which is a member of [`Read`](https://hackage.haskell.org/package/base/docs/Prelude.html#t:Read)."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 31,
   "metadata": {
    "attributes": {
     "classes": [
      "haskell:",
      "ghci"
     ],
     "id": "",
     "name": "\"code\""
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "True"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "read \"True\" || False"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 32,
   "metadata": {
    "attributes": {
     "classes": [
      "haskell:",
      "ghci"
     ],
     "id": "",
     "name": "\"code\""
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "12.0"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "read \"8.2\" + 3.8"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 33,
   "metadata": {
    "attributes": {
     "classes": [
      "haskell:",
      "ghci"
     ],
     "id": "",
     "name": "\"code\""
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "3"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "read \"5\" - 2"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 34,
   "metadata": {
    "attributes": {
     "classes": [
      "haskell:",
      "ghci"
     ],
     "id": "",
     "name": "\"code\""
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[1,2,3,4,3]"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "read \"[1,2,3,4]\" ++ [3]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "So far so good. Again, all types covered so far are in this typeclass.\n",
    "But what happens if we try to do just `read \"4\"`?"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 35,
   "metadata": {
    "attributes": {
     "classes": [
      "haskell:",
      "ghci"
     ],
     "id": "",
     "name": "\"code\""
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[]"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "reads \"4\""
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "What GHC is telling us here is that it doesn't know what we want in\n",
    "return. Notice that in the previous uses of [`read`](https://hackage.haskell.org/package/base/docs/Prelude.html#v:read) we did something with\n",
    "the result afterwards. That way, GHC could infer what kind of result we\n",
    "wanted out of our [`read`](https://hackage.haskell.org/package/base/docs/Prelude.html#v:read). If we used it as a boolean, it knew it had to\n",
    "return a [`Bool`](https://hackage.haskell.org/package/base/docs/Prelude.html#t:Bool). But now, it knows we want some type that is part of the\n",
    "[`Read`](https://hackage.haskell.org/package/base/docs/Prelude.html#t:Read) class, it just doesn't know which one. Let's take a look at the\n",
    "type signature of [`read`](https://hackage.haskell.org/package/base/docs/Prelude.html#v:read)."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 36,
   "metadata": {
    "attributes": {
     "classes": [
      "haskell:",
      "ghci"
     ],
     "id": "",
     "name": "\"code\""
    }
   },
   "outputs": [
    {
     "data": {
      "text/html": [
       "<style>/* Styles used for the Hoogle display in the pager */\n",
       ".hoogle-doc {\n",
       "display: block;\n",
       "padding-bottom: 1.3em;\n",
       "padding-left: 0.4em;\n",
       "}\n",
       ".hoogle-code {\n",
       "display: block;\n",
       "font-family: monospace;\n",
       "white-space: pre;\n",
       "}\n",
       ".hoogle-text {\n",
       "display: block;\n",
       "}\n",
       ".hoogle-name {\n",
       "color: green;\n",
       "font-weight: bold;\n",
       "}\n",
       ".hoogle-head {\n",
       "font-weight: bold;\n",
       "}\n",
       ".hoogle-sub {\n",
       "display: block;\n",
       "margin-left: 0.4em;\n",
       "}\n",
       ".hoogle-package {\n",
       "font-weight: bold;\n",
       "font-style: italic;\n",
       "}\n",
       ".hoogle-module {\n",
       "font-weight: bold;\n",
       "}\n",
       ".hoogle-class {\n",
       "font-weight: bold;\n",
       "}\n",
       ".get-type {\n",
       "color: green;\n",
       "font-weight: bold;\n",
       "font-family: monospace;\n",
       "display: block;\n",
       "white-space: pre-wrap;\n",
       "}\n",
       ".show-type {\n",
       "color: green;\n",
       "font-weight: bold;\n",
       "font-family: monospace;\n",
       "margin-left: 1em;\n",
       "}\n",
       ".mono {\n",
       "font-family: monospace;\n",
       "display: block;\n",
       "}\n",
       ".err-msg {\n",
       "color: red;\n",
       "font-style: italic;\n",
       "font-family: monospace;\n",
       "white-space: pre;\n",
       "display: block;\n",
       "}\n",
       "#unshowable {\n",
       "color: red;\n",
       "font-weight: bold;\n",
       "}\n",
       ".err-msg.in.collapse {\n",
       "padding-top: 0.7em;\n",
       "}\n",
       ".highlight-code {\n",
       "white-space: pre;\n",
       "font-family: monospace;\n",
       "}\n",
       ".suggestion-warning { \n",
       "font-weight: bold;\n",
       "color: rgb(200, 130, 0);\n",
       "}\n",
       ".suggestion-error { \n",
       "font-weight: bold;\n",
       "color: red;\n",
       "}\n",
       ".suggestion-name {\n",
       "font-weight: bold;\n",
       "}\n",
       "</style><span class='get-type'>read :: forall a. Read a => String -> a</span>"
      ],
      "text/plain": [
       "read :: forall a. Read a => String -> a"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    ":t read"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "See? It returns a type that's part of [`Read`](https://hackage.haskell.org/package/base/docs/Prelude.html#t:Read) but if we don't try to use it\n",
    "in some way later, it has no way of knowing which type. That's why we\n",
    "can use explicit __type annotations__. Type annotations are a way of\n",
    "explicitly saying what the type of an expression should be. We do that\n",
    "by adding `::` at the end of the expression and then specifying a type.\n",
    "Observe:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 37,
   "metadata": {
    "attributes": {
     "classes": [
      "haskell:",
      "ghci"
     ],
     "id": "",
     "name": "\"code\""
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "5"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "read \"5\" :: Int"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 38,
   "metadata": {
    "attributes": {
     "classes": [
      "haskell:",
      "ghci"
     ],
     "id": "",
     "name": "\"code\""
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "5.0"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "read \"5\" :: Float"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 39,
   "metadata": {
    "attributes": {
     "classes": [
      "haskell:",
      "ghci"
     ],
     "id": "",
     "name": "\"code\""
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "20.0"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "(read \"5\" :: Float) * 4"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 40,
   "metadata": {
    "attributes": {
     "classes": [
      "haskell:",
      "ghci"
     ],
     "id": "",
     "name": "\"code\""
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[1,2,3,4]"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "read \"[1,2,3,4]\" :: [Int]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 41,
   "metadata": {
    "attributes": {
     "classes": [
      "haskell:",
      "ghci"
     ],
     "id": "",
     "name": "\"code\""
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(3,'a')"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "read \"(3, 'a')\" :: (Int, Char)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Most expressions are such that the compiler can infer what their type is\n",
    "by itself. But sometimes, the compiler doesn't know whether to return a\n",
    "value of type [`Int`](https://hackage.haskell.org/package/base/docs/Prelude.html#t:Int) or [`Float`](https://hackage.haskell.org/package/base/docs/Prelude.html#t:Float) for an expression like `read \"5\"`. To see what\n",
    "the type is, Haskell would have to actually evaluate `read \"5\"`. But since\n",
    "Haskell is a statically typed language, it has to know all the types\n",
    "before the code is compiled (or in the case of GHCI, evaluated). So we\n",
    "have to tell Haskell: \"Hey, this expression should have this type, in\n",
    "case you don't know!\".\n",
    "\n",
    "__[`Enum`](https://hackage.haskell.org/package/base/docs/Prelude.html#t:Enum)__ members are sequentially ordered types — they can be enumerated.\n",
    "The main advantage of the [`Enum`](https://hackage.haskell.org/package/base/docs/Prelude.html#t:Enum) typeclass is that we can use its types in\n",
    "list ranges. They also have defined successors and predecessors, which\n",
    "you can get with the [`succ`](https://hackage.haskell.org/package/base/docs/Prelude.html#v:succ) and [`pred`](https://hackage.haskell.org/package/base/docs/Prelude.html#v:pred) functions. Types in this class: `()`,\n",
    "[`Bool`](https://hackage.haskell.org/package/base/docs/Prelude.html#t:Bool), [`Char`](https://hackage.haskell.org/package/base/docs/Prelude.html#t:Char), [`Ordering`](https://hackage.haskell.org/package/base/docs/Prelude.html#t:Ordering), [`Int`](https://hackage.haskell.org/package/base/docs/Prelude.html#t:Int), [`Integer`](https://hackage.haskell.org/package/base/docs/Prelude.html#t:Integer), [`Float`](https://hackage.haskell.org/package/base/docs/Prelude.html#t:Float) and [`Double`](https://hackage.haskell.org/package/base/docs/Prelude.html#t:Double)."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 42,
   "metadata": {
    "attributes": {
     "classes": [
      "haskell:",
      "ghci"
     ],
     "id": "",
     "name": "\"code\""
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "\"abcde\""
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "['a'..'e']"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 43,
   "metadata": {
    "attributes": {
     "classes": [
      "haskell:",
      "ghci"
     ],
     "id": "",
     "name": "\"code\""
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[LT,EQ,GT]"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "[LT .. GT]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 44,
   "metadata": {
    "attributes": {
     "classes": [
      "haskell:",
      "ghci"
     ],
     "id": "",
     "name": "\"code\""
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[3,4,5]"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "[3 .. 5]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 45,
   "metadata": {
    "attributes": {
     "classes": [
      "haskell:",
      "ghci"
     ],
     "id": "",
     "name": "\"code\""
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'C'"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "succ 'B'"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "__[`Bounded`](https://hackage.haskell.org/package/base/docs/Prelude.html#t:Bounded)__ members have an upper and a lower bound."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "> __Jupyter Note:__ Parentheses resolve ambiguity in the following expressions, see [IHaskell Issue #509 The type signature for ‘minBound’ lacks an accompanying binding](https://github.com/IHaskell/IHaskell/issues/509)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 46,
   "metadata": {
    "attributes": {
     "classes": [
      "haskell:",
      "ghci"
     ],
     "id": "",
     "name": "\"code\""
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "-9223372036854775808"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "(minBound :: Int)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 47,
   "metadata": {
    "attributes": {
     "classes": [
      "haskell:",
      "ghci"
     ],
     "id": "",
     "name": "\"code\""
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'\\1114111'"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "(maxBound :: Char)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 48,
   "metadata": {
    "attributes": {
     "classes": [
      "haskell:",
      "ghci"
     ],
     "id": "",
     "name": "\"code\""
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "True"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "(maxBound :: Bool)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 49,
   "metadata": {
    "attributes": {
     "classes": [
      "haskell:",
      "ghci"
     ],
     "id": "",
     "name": "\"code\""
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "False"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "(minBound :: Bool)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "[`minBound`](https://hackage.haskell.org/package/base/docs/Prelude.html#v:minBound) and [`maxBound`](https://hackage.haskell.org/package/base/docs/Prelude.html#v:maxBound) are interesting because they have a type of\n",
    "`(Bounded a) => a`. In a sense they are polymorphic constants.\n",
    "\n",
    "All tuples are also part of [`Bounded`](https://hackage.haskell.org/package/base/docs/Prelude.html#t:Bounded) if the components are also in it."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 50,
   "metadata": {
    "attributes": {
     "classes": [
      "haskell:",
      "ghci"
     ],
     "id": "",
     "name": "\"code\""
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(True,9223372036854775807,'\\1114111')"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "(maxBound :: (Bool, Int, Char))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "__[`Num`](https://hackage.haskell.org/package/base/docs/Prelude.html#t:Num)__ is a numeric typeclass. Its members have the property of being able\n",
    "to act like numbers. Let's examine the type of a number."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 51,
   "metadata": {
    "attributes": {
     "classes": [
      "haskell:",
      "ghci"
     ],
     "id": "",
     "name": "\"code\""
    }
   },
   "outputs": [
    {
     "data": {
      "text/html": [
       "<style>/* Styles used for the Hoogle display in the pager */\n",
       ".hoogle-doc {\n",
       "display: block;\n",
       "padding-bottom: 1.3em;\n",
       "padding-left: 0.4em;\n",
       "}\n",
       ".hoogle-code {\n",
       "display: block;\n",
       "font-family: monospace;\n",
       "white-space: pre;\n",
       "}\n",
       ".hoogle-text {\n",
       "display: block;\n",
       "}\n",
       ".hoogle-name {\n",
       "color: green;\n",
       "font-weight: bold;\n",
       "}\n",
       ".hoogle-head {\n",
       "font-weight: bold;\n",
       "}\n",
       ".hoogle-sub {\n",
       "display: block;\n",
       "margin-left: 0.4em;\n",
       "}\n",
       ".hoogle-package {\n",
       "font-weight: bold;\n",
       "font-style: italic;\n",
       "}\n",
       ".hoogle-module {\n",
       "font-weight: bold;\n",
       "}\n",
       ".hoogle-class {\n",
       "font-weight: bold;\n",
       "}\n",
       ".get-type {\n",
       "color: green;\n",
       "font-weight: bold;\n",
       "font-family: monospace;\n",
       "display: block;\n",
       "white-space: pre-wrap;\n",
       "}\n",
       ".show-type {\n",
       "color: green;\n",
       "font-weight: bold;\n",
       "font-family: monospace;\n",
       "margin-left: 1em;\n",
       "}\n",
       ".mono {\n",
       "font-family: monospace;\n",
       "display: block;\n",
       "}\n",
       ".err-msg {\n",
       "color: red;\n",
       "font-style: italic;\n",
       "font-family: monospace;\n",
       "white-space: pre;\n",
       "display: block;\n",
       "}\n",
       "#unshowable {\n",
       "color: red;\n",
       "font-weight: bold;\n",
       "}\n",
       ".err-msg.in.collapse {\n",
       "padding-top: 0.7em;\n",
       "}\n",
       ".highlight-code {\n",
       "white-space: pre;\n",
       "font-family: monospace;\n",
       "}\n",
       ".suggestion-warning { \n",
       "font-weight: bold;\n",
       "color: rgb(200, 130, 0);\n",
       "}\n",
       ".suggestion-error { \n",
       "font-weight: bold;\n",
       "color: red;\n",
       "}\n",
       ".suggestion-name {\n",
       "font-weight: bold;\n",
       "}\n",
       "</style><span class='get-type'>20 :: forall {a}. Num a => a</span>"
      ],
      "text/plain": [
       "20 :: forall {a}. Num a => a"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    ":t 20"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "It appears that whole numbers are also polymorphic constants. They can\n",
    "act like any type that's a member of the [`Num`](https://hackage.haskell.org/package/base/docs/Prelude.html#t:Num) typeclass."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 52,
   "metadata": {
    "attributes": {
     "classes": [
      "haskell:",
      "ghci"
     ],
     "id": "",
     "name": "\"code\""
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "20"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "20 :: Int"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 53,
   "metadata": {
    "attributes": {
     "classes": [
      "haskell:",
      "ghci"
     ],
     "id": "",
     "name": "\"code\""
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "20"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "20 :: Integer"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 54,
   "metadata": {
    "attributes": {
     "classes": [
      "haskell:",
      "ghci"
     ],
     "id": "",
     "name": "\"code\""
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "20.0"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "20 :: Float"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 55,
   "metadata": {
    "attributes": {
     "classes": [
      "haskell:",
      "ghci"
     ],
     "id": "",
     "name": "\"code\""
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "20.0"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "20 :: Double"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Those are types that are in the [`Num`](https://hackage.haskell.org/package/base/docs/Prelude.html#t:Num) typeclass. If we examine the type of\n",
    "[`*`](https://hackage.haskell.org/package/base/docs/Prelude.html#v:-42-), we'll see that it accepts all numbers."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 56,
   "metadata": {
    "attributes": {
     "classes": [
      "haskell:",
      "ghci"
     ],
     "id": "",
     "name": "\"code\""
    }
   },
   "outputs": [
    {
     "data": {
      "text/html": [
       "<style>/* Styles used for the Hoogle display in the pager */\n",
       ".hoogle-doc {\n",
       "display: block;\n",
       "padding-bottom: 1.3em;\n",
       "padding-left: 0.4em;\n",
       "}\n",
       ".hoogle-code {\n",
       "display: block;\n",
       "font-family: monospace;\n",
       "white-space: pre;\n",
       "}\n",
       ".hoogle-text {\n",
       "display: block;\n",
       "}\n",
       ".hoogle-name {\n",
       "color: green;\n",
       "font-weight: bold;\n",
       "}\n",
       ".hoogle-head {\n",
       "font-weight: bold;\n",
       "}\n",
       ".hoogle-sub {\n",
       "display: block;\n",
       "margin-left: 0.4em;\n",
       "}\n",
       ".hoogle-package {\n",
       "font-weight: bold;\n",
       "font-style: italic;\n",
       "}\n",
       ".hoogle-module {\n",
       "font-weight: bold;\n",
       "}\n",
       ".hoogle-class {\n",
       "font-weight: bold;\n",
       "}\n",
       ".get-type {\n",
       "color: green;\n",
       "font-weight: bold;\n",
       "font-family: monospace;\n",
       "display: block;\n",
       "white-space: pre-wrap;\n",
       "}\n",
       ".show-type {\n",
       "color: green;\n",
       "font-weight: bold;\n",
       "font-family: monospace;\n",
       "margin-left: 1em;\n",
       "}\n",
       ".mono {\n",
       "font-family: monospace;\n",
       "display: block;\n",
       "}\n",
       ".err-msg {\n",
       "color: red;\n",
       "font-style: italic;\n",
       "font-family: monospace;\n",
       "white-space: pre;\n",
       "display: block;\n",
       "}\n",
       "#unshowable {\n",
       "color: red;\n",
       "font-weight: bold;\n",
       "}\n",
       ".err-msg.in.collapse {\n",
       "padding-top: 0.7em;\n",
       "}\n",
       ".highlight-code {\n",
       "white-space: pre;\n",
       "font-family: monospace;\n",
       "}\n",
       ".suggestion-warning { \n",
       "font-weight: bold;\n",
       "color: rgb(200, 130, 0);\n",
       "}\n",
       ".suggestion-error { \n",
       "font-weight: bold;\n",
       "color: red;\n",
       "}\n",
       ".suggestion-name {\n",
       "font-weight: bold;\n",
       "}\n",
       "</style><span class='get-type'>(*) :: forall a. Num a => a -> a -> a</span>"
      ],
      "text/plain": [
       "(*) :: forall a. Num a => a -> a -> a"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    ":t (*)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "It takes two numbers of the same type and returns a number of that type.\n",
    "That's why `(5 :: Int) * (6 :: Integer)` will result in a type error\n",
    "whereas `5 * (6 :: Integer)` will work just fine and produce an [`Integer`](https://hackage.haskell.org/package/base/docs/Prelude.html#t:Integer)\n",
    "because `5` can act like an [`Integer`](https://hackage.haskell.org/package/base/docs/Prelude.html#t:Integer) or an [`Int`](https://hackage.haskell.org/package/base/docs/Prelude.html#t:Int).\n",
    "\n",
    "To join [`Num`](https://hackage.haskell.org/package/base/docs/Prelude.html#t:Num), a type must already be friends with [`Show`](https://hackage.haskell.org/package/base/docs/Prelude.html#t:Show) and `Eq`.\n",
    "\n",
    "__[`Integral`](https://hackage.haskell.org/package/base/docs/Prelude.html#t:Integral)__ is also a numeric typeclass. [`Num`](https://hackage.haskell.org/package/base/docs/Prelude.html#t:Num) includes all numbers,\n",
    "including real numbers and integral numbers, [`Integral`](https://hackage.haskell.org/package/base/docs/Prelude.html#t:Integral) includes only\n",
    "integral (whole) numbers. In this typeclass are [`Int`](https://hackage.haskell.org/package/base/docs/Prelude.html#t:Int) and [`Integer`](https://hackage.haskell.org/package/base/docs/Prelude.html#t:Integer).\n",
    "\n",
    "__[`Floating`](https://hackage.haskell.org/package/base/docs/Prelude.html#t:Floating)__ includes only floating point numbers, so [`Float`](https://hackage.haskell.org/package/base/docs/Prelude.html#t:Float) and [`Double`](https://hackage.haskell.org/package/base/docs/Prelude.html#t:Double).\n",
    "\n",
    "A very useful function for dealing with numbers is __[`fromIntegral`](https://hackage.haskell.org/package/base/docs/Prelude.html#v:fromIntegral)__. It has\n",
    "a type declaration of `fromIntegral :: (Num b, Integral a) => a -> b`.\n",
    "From its type signature we see that it takes an integral number and\n",
    "turns it into a more general number. That's useful when you want\n",
    "integral and floating point types to work together nicely. For instance,\n",
    "the [`length`](https://hackage.haskell.org/package/base/docs/Prelude.html#v:length) function has a type declaration of `length :: [a] -> Int`\n",
    "instead of having a more general type of\n",
    "`(Num b) => length :: [a] -> b`.\n",
    "I think that's there for historical reasons or something, although in\n",
    "my opinion, it's pretty stupid. Anyway, if we try to get a length of a\n",
    "list and then add it to `3.2`, we'll get an error because we tried to add\n",
    "together an [`Int`](https://hackage.haskell.org/package/base/docs/Prelude.html#t:Int) and a floating point number. So to get around this, we\n",
    "do `fromIntegral (length [1,2,3,4]) + 3.2` and it all works out.\n",
    "\n",
    "Notice that [`fromIntegral`](https://hackage.haskell.org/package/base/docs/Prelude.html#v:fromIntegral) has several class constraints in its type\n",
    "signature. That's completely valid and as you can see, the class\n",
    "constraints are separated by commas inside the parentheses."
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Haskell",
   "language": "haskell",
   "name": "haskell"
  },
  "language_info": {
   "codemirror_mode": "ihaskell",
   "file_extension": ".hs",
   "mimetype": "text/x-haskell",
   "name": "haskell",
   "pygments_lexer": "Haskell",
   "version": "9.2.5"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}


================================================
FILE: notebook/04-syntax-in-functions.ipynb
================================================
{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {
    "tags": []
   },
   "source": [
    "Syntax in Functions\n",
    "===================\n",
    "\n",
    "Pattern matching\n",
    "----------------\n",
    "\n",
    "<img src=\"img/pattern.png\" title=\"four!\" style=\"background-color:white;float:right;margin-left:2em;\" />\n",
    "\n",
    "This chapter will cover some of Haskell's cool syntactic constructs and\n",
    "we'll start with pattern matching. Pattern matching consists of\n",
    "specifying patterns to which some data should conform and then checking\n",
    "to see if it does and deconstructing the data according to those\n",
    "patterns.\n",
    "\n",
    "When defining functions, you can define separate function bodies for\n",
    "different patterns. This leads to really neat code that's simple and\n",
    "readable. You can pattern match on any data type — numbers, characters,\n",
    "lists, tuples, etc. Let's make a really trivial function that checks if\n",
    "the number we supplied to it is a seven or not."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "> __Jupyter Note:__ We'll turn off the [automatic linting for IHaskell](https://github.com/IHaskell/IHaskell/wiki#opt-no-lint) first."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    ":opt no-lint"
   ]
  },
  {
   "cell_type": "code
Download .txt
gitextract_njh7ebiu/

├── .devcontainer/
│   ├── Dockerfile
│   └── devcontainer.json
├── .gitignore
├── Dockerfile
├── LICENSE
├── README.md
├── anchordoc/
│   ├── LICENSE
│   ├── README.md
│   ├── Setup.hs
│   ├── anchordoc.cabal
│   ├── notebooks.anchordoc.sh
│   ├── src/
│   │   └── Main.hs
│   └── stack.yaml
├── docker-compose.yml
├── flake.nix
├── kernels/
│   └── haskell.nix
├── kernels.nix
├── notebook/
│   ├── 00-preface.ipynb
│   ├── 01-introduction.ipynb
│   ├── 02-starting-out.ipynb
│   ├── 03-types-and-typeclasses.ipynb
│   ├── 04-syntax-in-functions.ipynb
│   ├── 05-recursion.ipynb
│   ├── 06-higher-order-functions.ipynb
│   ├── 07-modules.ipynb
│   ├── 08-making-our-own-types-and-typeclasses.ipynb
│   ├── 09-input-and-output.ipynb
│   ├── 10-functionally-solving-problems.ipynb
│   ├── 11-functors-applicative-functors-and-monoids.ipynb
│   ├── 12-a-fistful-of-monads.ipynb
│   ├── 13-for-a-few-monads-more.ipynb
│   └── 14-zippers.ipynb
└── notebook_extra/
    ├── WidgetChart.ipynb
    ├── WidgetDiagram.ipynb
    └── WidgetRevival.ipynb
Condensed preview — 35 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (1,912K chars).
[
  {
    "path": ".devcontainer/Dockerfile",
    "chars": 47,
    "preview": "FROM ghcr.io/ihaskell/ihaskell-notebook:master\n"
  },
  {
    "path": ".devcontainer/devcontainer.json",
    "chars": 1727,
    "preview": "// For format details, see https://aka.ms/devcontainer.json. For config options, see the README at:\n// https://github.co"
  },
  {
    "path": ".gitignore",
    "chars": 176,
    "preview": "notebook/*.txt\nnotebook/Geometry.dyn_hi\nnotebook/Geometry.dyn_o\nnotebook/Geometry.hi\nnotebook/Geometry.hs\nnotebook/Geome"
  },
  {
    "path": "Dockerfile",
    "chars": 799,
    "preview": "# Dockerfile for mybinder.org\n#\n# Test this Dockerfile:\n#\n#     docker build -t learn-you-a-haskell .\n#     docker run -"
  },
  {
    "path": "LICENSE",
    "chars": 51,
    "preview": "https://creativecommons.org/licenses/by-nc-sa/3.0/\n"
  },
  {
    "path": "README.md",
    "chars": 7378,
    "preview": "# Learn You a Haskell for Great Good!\n\n## Read the book right now\n\n### Read the book method 1: [mybinder.org](https://my"
  },
  {
    "path": "anchordoc/LICENSE",
    "chars": 1524,
    "preview": "Copyright James D. Brock (c) 2019\n\nAll rights reserved.\n\nRedistribution and use in source and binary forms, with or with"
  },
  {
    "path": "anchordoc/README.md",
    "chars": 12,
    "preview": "# anchordoc\n"
  },
  {
    "path": "anchordoc/Setup.hs",
    "chars": 46,
    "preview": "import Distribution.Simple\nmain = defaultMain\n"
  },
  {
    "path": "anchordoc/anchordoc.cabal",
    "chars": 889,
    "preview": "name:                anchordoc\nversion:             0.1.0.0\n-- synopsis:\n-- description:\nhomepage:            https://gi"
  },
  {
    "path": "anchordoc/notebooks.anchordoc.sh",
    "chars": 175,
    "preview": "#! /usr/bin/env bash\n\nfor n in $(ls ../notebook/*.ipynb); do\n    echo $n \" ...\"\n    stack exec anchordoc < $n > ../noteb"
  },
  {
    "path": "anchordoc/src/Main.hs",
    "chars": 6107,
    "preview": "{-# LANGUAGE OverloadedStrings #-}\n{-# LANGUAGE ScopedTypeVariables #-}\n{-# LANGUAGE LambdaCase #-}\n{-# LANGUAGE TypeFam"
  },
  {
    "path": "anchordoc/stack.yaml",
    "chars": 29,
    "preview": "resolver: nightly-2019-09-13\n"
  },
  {
    "path": "docker-compose.yml",
    "chars": 242,
    "preview": "version: '3.3'\n\nservices:\n   ihaskell-notebook:\n     build: .\n     ports:\n       - \"8888:8888\"\n     volumes:\n       - ./"
  },
  {
    "path": "flake.nix",
    "chars": 1518,
    "preview": "{\n  description = \"Learn You a Haskell for Great Good! Jupyter adaptation\";\n\n  inputs.flake-utils.url = \"github:numtide/"
  },
  {
    "path": "kernels/haskell.nix",
    "chars": 146,
    "preview": "{\n  name,\n  availableKernels,\n  extraArgs,\n}:\navailableKernels.haskell {\n  inherit name;\n  inherit (extraArgs) pkgs;\n  d"
  },
  {
    "path": "kernels.nix",
    "chars": 153,
    "preview": "{pkgs, ...}: {\n  # kernel.python.minimal = {\n  #   enable = true;\n  # };\n  kernel.haskell.\"1\" = {\n    enable = true;\n   "
  },
  {
    "path": "notebook/00-preface.ipynb",
    "chars": 2626,
    "preview": "{\n \"cells\": [\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"<img src=\\\"img/cover.png\\\" style=\\\""
  },
  {
    "path": "notebook/01-introduction.ipynb",
    "chars": 8483,
    "preview": "{\n \"cells\": [\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Introduction\\n\",\n    \"============\\"
  },
  {
    "path": "notebook/02-starting-out.ipynb",
    "chars": 87874,
    "preview": "{\n \"cells\": [\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"<img src=\\\"img/startingout.png\\\" ti"
  },
  {
    "path": "notebook/03-types-and-typeclasses.ipynb",
    "chars": 75732,
    "preview": "{\n \"cells\": [\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Types and Typeclasses\\n\",\n    \"===="
  },
  {
    "path": "notebook/04-syntax-in-functions.ipynb",
    "chars": 50457,
    "preview": "{\n \"cells\": [\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {\n    \"tags\": []\n   },\n   \"source\": [\n    \"Syntax in Functi"
  },
  {
    "path": "notebook/05-recursion.ipynb",
    "chars": 25309,
    "preview": "{\n \"cells\": [\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Recursion\\n\",\n    \"=========\\n\",\n  "
  },
  {
    "path": "notebook/06-higher-order-functions.ipynb",
    "chars": 90748,
    "preview": "{\n \"cells\": [\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Higher order functions\\n\",\n    \"==="
  },
  {
    "path": "notebook/07-modules.ipynb",
    "chars": 160005,
    "preview": "{\n \"cells\": [\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Modules\\n\",\n    \"=======\\n\",\n    \"\\"
  },
  {
    "path": "notebook/08-making-our-own-types-and-typeclasses.ipynb",
    "chars": 243211,
    "preview": "{\n \"cells\": [\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Making Our Own Types and Typeclasse"
  },
  {
    "path": "notebook/09-input-and-output.ipynb",
    "chars": 219349,
    "preview": "{\n \"cells\": [\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Input and Output\\n\",\n    \"========="
  },
  {
    "path": "notebook/10-functionally-solving-problems.ipynb",
    "chars": 50300,
    "preview": "{\n \"cells\": [\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Functionally Solving Problems\\n\",\n "
  },
  {
    "path": "notebook/11-functors-applicative-functors-and-monoids.ipynb",
    "chars": 286303,
    "preview": "{\n \"cells\": [\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Functors, Applicative Functors and "
  },
  {
    "path": "notebook/12-a-fistful-of-monads.ipynb",
    "chars": 135868,
    "preview": "{\n \"cells\": [\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"A Fistful of Monads\\n\",\n    \"======"
  },
  {
    "path": "notebook/13-for-a-few-monads-more.ipynb",
    "chars": 190123,
    "preview": "{\n \"cells\": [\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"For a Few Monads More\\n\",\n    \"===="
  },
  {
    "path": "notebook/14-zippers.ipynb",
    "chars": 63177,
    "preview": "{\n \"cells\": [\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"Zippers\\n\",\n    \"=======\\n\",\n    \"\\"
  },
  {
    "path": "notebook_extra/WidgetChart.ipynb",
    "chars": 3086,
    "preview": "{\n \"cells\": [\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"## Demonstration combining Widgets "
  },
  {
    "path": "notebook_extra/WidgetDiagram.ipynb",
    "chars": 3899,
    "preview": "{\n \"cells\": [\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"## Demonstration combining Widgets "
  },
  {
    "path": "notebook_extra/WidgetRevival.ipynb",
    "chars": 6930,
    "preview": "{\n \"cells\": [\n  {\n   \"cell_type\": \"markdown\",\n   \"metadata\": {},\n   \"source\": [\n    \"# 💙 <span style=\\\"color:navy;text-s"
  }
]

About this extraction

This page contains the full source code of the jamesdbrock/learn-you-a-haskell-notebook GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 35 files (1.6 MB), approximately 500.0k tokens. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!