# Introduction

Install Haskell 8.6.5. Make sure you're using the right version. Should be available on lab machines. Installing locally is also a good idea.

Launch the interactive Haskell shell (`ghci`) from the UNIX command prompt.

``````# ghci
GHCi, version 8.6.5: http://www.haskell.org/ghc/  :? for help
Prelude>``````

### Numbers, Booleans, Strings, Characters

Try out integers, floating-point numbers, booleans strings, characters. Try some expressions that result in type errors.

``````Prelude> 4
Prelude> :set prompt "> "
> 4
> 4.0
> 4 + 4
> 4 + 4.0
> 'a'
> "a"
> "a" + "b"
> "a" ++ "b"
> "a" ++ 'b'
> True
> true``````

### Types

We'll talk about types in much more detail later. For now, let's experiment a little.

``````> :type True
> :t True``````

#### Numeric Types

``> :t 4``

We'll dig into this in detail later. For now, read `Num p => p` as "`Int` and `Float` and `Double` and every other numeric type you can think of". We can "convert" `4` to one of these specific numeric types with an explicit type ascription, using the `::` syntax.

``````> :t (4 :: Int)
(4 :: Int) :: Int
> :t 4 :: Int
4 :: Int :: Int
> :t 4 :: Integer
4 :: Integer :: Integer
> :t 4 :: Float
4 :: Float :: Float
> :t 4 :: Double
4 :: Double :: Double
> :t 4.0 :: Double
4.0 :: Double :: Double
> :t 4.0 :: Int``````

Notice that operators like `(+)` can work on many different kinds of numbers.

``````> 4 + 5
> (+) 4 5
> :t (+)
(+) :: Num a => a -> a -> a``````

You can read the type for `(+)` as saying "`(+)` takes two `Int`s or two `Float`s or two `Double`s or two values of any other numeric type and returns another number of the same type as the arguments". Haskell automatically infers the specific types based on how the expressions are used. But we can also explicitly tell Haskell which types we want using type ascription.

``````> :t (4 :: Int) + (5 :: Int)
> :t (4 + 5) :: Int
> :t (4 + 5) :: Float
> :t (4 :: Float) + 5
> :t (4 :: Float) + (5 :: Double)
> :t (4 :: Float) + (5 :: Int)``````

#### Strings as Lists of Characters

Notice that strings are lists of characters, written `[Char]`. We can define `String` to be another way of writing the type `[Char]`.

``````> :t 'a'
> :t "a"
> type String = [Char]
> :t "a" :: String
> :t (++) :: String -> String -> String``````

#### Tuples

``````> :t ('a', True)
> :t ('a', True, 1)
> :t ('a', (True, 1))``````

### History and Tab Completion

``````> <UP>
> :<TAB>               -- lots of commands
> :set <TAB>           -- lots of options and flags
> :set prompt "> "``````

### Let-bindings

``````> let x = 1
> x + 1
> let y = 2
> x + y``````

If you're familar with mutable variables in other languages, this is not the same thing. These variable bindings never change...

``````> let z = 0
> let z = 1                     -- "shadowing"
> let z = z + 1                 -- recursive def (not shadowing)
> z                             -- "forces" evaluation (diverges)
> Ctrl-C                        -- to interrupt
> Ctrl-D                        -- to quit GHCI``````

Multiple bindings in a single `let`.

``````> let a = 1; b = 2              -- multiple bindings
> let a = 1; b = 2;             -- optional last semi-colon
> let {a = 1; b = 2;}           -- optional braces``````

Top-level vs. local let-bindings.

``````let x = 1                     -- "global" binding
let y = 2 in y + y            -- "local" binding
y                             -- not in scope
let y = 6
let y = 5 in y + y            -- previous binding "shadowed" (locally)
y``````

### Simple Function Definitions

``````> let add3 x = x + 3

> let add x y = x + y
... No instance for Show ...  -- more on this next time

> let also_add (x, y) = x + y

> also_add 1 2                  -- error
> add (1, 2)                    -- error``````

The the `add` function takes two arguments, whereas the `also_add` function takes a single argument (a 2-element tuple, a.k.a. a pair).

All functions in Haskell take exactly one argument and produce exactly one value in return. But what about the "multi-argument" functions above?

``````> let add4 = add 4               -- "currying" or partial application

We'll talk much more about functions in due course.

## Source Files

So far, we've used the interactive shell. Now let's create a standalone Haskell source file called `Introduction.hs`. Unlike in the shell, top-level definitions in Haskell source files do not start with `let`. Instead, they are written like equations.

``minutesPerDay = 60 * 24``

Definitions can refer to subsequent definitions later in the file. Helper definitions can help improve readability and maintainability.

``````minutesPerDay = minutesPerHour * hoursPerDay
minutesPerHour = 60
hoursPerDay = 24``````

All definitions are at the "top-level" and are mutually recursive. These two features help make Haskell definitions read more like math.

Local variables can help improve readability and maintainability, by emphasizing the scope of the definitions. For example, instead of the previous three top-level definitions, we can use two locally defined bindings:

``````minutesPerDay =
let minutesPerHour = 60 in
let hoursPerDay = 24 in
minutesPerHour * hoursPerDay``````

Or better yet:

``````minutesPerDay =
let
minutesPerHour = 60
hoursPerDay = 24
in
minutesPerHour * hoursPerDay``````

Alternatively, where-clauses can be used instead of let-bindings.

``````minutesPerDay = minutesPerHour * hoursPerDay
where minutesPerHour = 60
hoursPerDay = 24``````

Like with let-bindings, `minutesPerHour` and `hoursPerDay` are not accessible outside this definition.

For both let-bindings and where-clauses, can choose indendation depth but must choose the same starting column for all variables being defined. So, there are many possible formatting styles. Here's another one.

``````minutesPerDay      = minutesPerHour * hoursPerDay where
minutesPerHour = 60
hoursPerDay    = 24``````

### Booleans and Guarded Definitions

``````> :t True
> :t 1 == 2
> :t 1 < 2``````

If-then-else expressions.

``````absoluteValue n =
if n >= 0
then n
else -1 * n``````

Alternatively:

``````absoluteValue n
| n >= 0 = n
| n <  0 = -1 * n``````

We can use `otherwise` as the last, "catch-all" guard. And we can negate `n` more concisely.

``````absoluteValue n
| n >= 0    = n
| otherwise = -n``````

``````-- single line comment

{- multi-line comment

-}``````

Load a source file from the shell.

``````> :load Introduction.hs
> :l Introduction.hs
> :l Introduction
> :r``````

## Library Documentation

The documentation for Haskell libraries will be very useful throughout the course. `Prelude` is a good place to start browsing.

This documentation should also be installed locally somewhere, such as `file:///Library/Haskell/doc/start.html` on a Mac; then click "Libraries".

## Hello, world!

Okay, we've said hello to the Haskell world. But where was printing "Hello, world!" to the output console? Patience...