# Haskell 2016Edit

Notes made while (re-)learning Haskell in 2016.

## Resources

### Books

- Learn You a Haskell for Great Good! (readable online for free)
- Haskell Programming from first principles (still in early access)
- Real World Haskell (O’Reilly, readable online for free)
- Maybe Haskell (non-free)

### Practice problems

### Tutorials

- Write Yourself a Scheme in 48 Hours
- Hitchhikers guide to Haskell
- The Monad Challenges
- Bryan O’Sullivan’s CS240H lecture notes (Winter)
- Bryan O’Sullivan’s CS240H lecture notes (Spring)

### Reference

### Meta: How to learn Haskell

### Other links

## Notes

### Installation

```
$ brew install ghc cabal-install
```

### Command line

```
$ ghci # Start a REPL.
$ runhaskell src.hs # Run code without separate compilation step.
$ runghc src.hs # Equivalent to runhaskell.
$ ghc --make src.hs # Compile.
$ ghc-pkg list # See installed packages.
```

`ghci`

`:?`

: show help`:cd [directory]`

: change working directory`:info [name]`

: show information about`name`

(a type, a typeclass, a binding etc)`:load [path]`

: load module from`path`

(relative to working directory, or absolute, with or without`.hs`

extension)`:m +[module]`

: load`module`

`:set +t`

: show type information for each evaluated expression`:set prompt "ghci> "`

: override default prompt`:show bindings`

: show all bound variables`:type [expression]`

(`:t [expression]`

): show the type for the given expression`:unset +t`

: don’t show type information`it`

: variable bound to the value of the last evaluated expression

### Prelude functions

`&&`

::`Bool -> Bool -> Bool`

…*short-circuiting boolean operator.*`++`

::`[a] -> [a] -> [a]`

`break`

::`(a -> Bool) -> [a] -> ([a], [a])`

…*breaks a list into two (consumes input while predicate fails).*`span`

::`(a -> Bool) -> [a] -> ([a], [a])`

…*breaks a list into two (consumes input while predicate succeeds).*`ceiling`

::`(Integral b, RealFrac a) => a -> b`

`splitAt`

::`Int -> [a] -> ([a], [a])`

`takeWhile`

::`(a -> Bool) -> [a] -> [a]`

`dropWhile`

::`(a -> Bool) -> [a] -> [a]`

`compare`

::`Ord a => a -> a -> Ordering`

`concat`

::`Foldable t => t [a] -> [a]`

`drop`

::`Int -> [a] -> [a]`

`elem`

::`(Eq a, Foldable t) => a -> t a -> Bool`

`zip`

::`[a] -> [b] -> [(a, b)]`

) …*also has variants for up to 7 lists (*`zip7`

).`zipWith`

::`(a -> b -> c) -> [a] -> [b] -> [c]`

) …*also has variants for up to 7 lists (*`zipWith7`

).`notElem`

::`(Eq a, Foldable t) => a -> t a -> Bool`

`error`

::`[Char] -> a`

`floor`

::`(Integral b, RealFrac a) => a -> b`

`fromIntegral`

::`(Integral a, Num b) => a -> b`

`fst`

::`(a, b) -> a`

`head`

::`[a] -> a`

…*first element of list (raises an exception if applied to an empty list)*`init`

…*all but last element of a list (raises exception if applied to an empty list)*`last`

…*last element of a list (raises exception if applied to an empty list)*`length`

::`Foldable t => t a -> Int`

`lines`

::`String -> [String]`

`mod`

::`Integral a => a -> a -> a`

…*modulo (remainder after division)*`filter`

::`(a -> Bool) -> [a] -> [a]`

`not`

::`Bool -> Bool`

`null`

::`Foldable t => t a -> Bool`

…*indicates whether a list is empty*`odd`

::`Integral a => a -> Bool`

`even`

::`Integral a => a -> Bool`

`map`

::`(a -> b) -> [a] -> [b]`

…*but consider using*`fmap`

instead.`negate`

::`Num a => a -> a`

`pred`

::`Enum a => a -> a`

`print`

::`Show a => a -> IO ()`

`read`

::`Read a => String -> a`

`show`

::`Show a => a -> String`

`readFile`

::`FilePath -> IO String`

`reverse`

::`[a] -> [a]`

`round`

::`(Integral b, RealFrac a) => a -> b`

`snd`

::`(a, b) -> b`

`sqrt`

::`Floating a => a -> a`

`succ`

::`Enum a => a -> a`

`tail`

::`[a] -> [a]`

…*non-head part of list (raises an exception if applied to an empty list)*`take`

::`Int -> [a] -> [a]`

`truncate`

::`(Integral b, RealFrac a) => a -> b`

`unlines`

::`[String] -> String`

`words`

::`String -> [String]`

`unwords`

::`[String] -> String`

`||`

::`Bool -> Bool -> Bool`

…*short-circuiting boolean operator*`and`

::`Foldable t => t Bool -> Bool`

`or`

::`Foldable t => t Bool -> Bool`

`all`

::`Foldable t => (a -> Bool) -> t a -> Bool`

`any`

::`Foldable t => (a -> Bool) -> t a -> Bool`

`seq`

::`a -> b -> b`

…*force non-lazy evaluation of first argument, then return second argument*`intercalate`

::`[a] -> [[a]] -> [a]`

`Data.Bits`

`.|.`

::`Bits a => a -> a -> a`

`.&.`

::`Bits a => a -> a -> a`

`shiftL`

::`Bits a => a -> Int -> a`

`shiftR`

::`Bits a => a -> Int -> a`

`Data.Char`

`digitToInt`

::`Char -> Int`

`ord`

::`Char -> Int`

`toUpper`

::`Char -> Char`

`Data.List`

`isInfixOf`

::`Eq a => [a] -> [a] -> Bool`

`isPrefixOf`

::`Eq a => [a] -> [a] -> Bool`

`isSuffixOf`

::`Eq a => [a] -> [a] -> Bool`

`tails`

::`[a] -> [[a]]`

…*returns all tails of a list*

### Data.ratio

`%`

::`Integral a => a -> a -> Ratio a`

`Debug.Trace`

`trace`

::`String -> a -> a`

`traceM`

::`String -> m ()`

(for use in`do`

notation)

`Numeric`

`showHex`

::`(Integral a, Show a) => a -> ShowS`

### Syntax

`--`

: begin a single-line comment`{- ... -}`

: in-line comment`if`

/`then`

/`else`

: conditional expression`$`

: function application (low precedence)`.`

: function composition (`(f . g) x`

is same as`f (g x)`

).`let`

+`in`

: create bound variables with the scope of an expression`where`

: like`let`

, but at top level of equation; not an expression`case (something) of (pattern) -> expression`

: pattern matching within expressions`|`

: guard (additionally restricts a pattern match)``fn``

(backticks): apply`fn`

in infix position`foo@(x:xs)`

("as-pattern"): refer to entirety of pattern match contents`::`

: disambiguate a type (eg.`read "5" :: Double`

)

### Importing modules

```
import Data.Set -- import everything from Data.Set (unqualified dump into top-level scope)
import Data.Set (member, union) -- import only named bindings
import qualified Data.Set -- import everything, but bound as Data.Set.{name}
import qualified Data.Set as Set -- import using an alias Set.{name}
import qualified Data.Set as Set (member, union) -- partial, aliased, qualified import
```

### Defining modules

```
-- Simple: Foo.hs
module Foo (bar, baz) where
bar = 1
baz = id
-- Nested: Bar/Baz.hs
module Bar.Baz (
, Thing -- export (abstract/opaque) type but not constructor(s)
, Other(..) -- exports type and constructors (for pattern matching etc)
, x
) where
data Thing = Thing Int
data Other = Other String
x = 2
```

### Types

`Double`

: double-precision floating point.`Float`

: single-precision floating point.`Int`

: fixed precision*signed*integer (bounds are architecture-dependent and given by`maxBound :: Int`

and`minBound :: Int`

).`Word`

: fixed precision*unsigned*integer (bounds:`minBound :: Word`

— ie. 0 — and`maxBound :: Word`

).`Integer`

: arbitrary precision integer.

### Defining new types

```
-- "Thing" type constructor (for pattern matching)
-- "Thing" value constructor (for creating values of the type)
data Thing = Thing Int String [String]
deriving (Eq, Show)
-- Record syntax (note: no trailing comma allowed)
data Thing = Thing {
customerID :: CustomerID,
customerName :: String,
customerAddress :: [String]
} deriving (Eq, Show)
-- Create values using either named fields:
myThing = Thing { customerID = 1234, customerName = "Jane", customerAddress = ["PO Box 1"] }
-- Or anonymous, ordered fields:
myThing = Thing 1234 "John" ["1 Infinite Loop"]
-- Algebraic types with multiple value constructors
data PaymentRecord = CreditCard | CashAccount
data Color = Red | Green | Blue deriving (Eq, Show)
-- Create a synonym for an existing type
type RecordLocator = String
-- Same, but for a tuple
type ContactDetails = (Name, PhoneNumber, Address)
-- Wrap a type to present it as something else (eg. List as ZipList).
-- Can only have one value constructor, and constructor can only have one field.
newtype ZipList a = ZipList { getZipList :: [a] }
newtype CharList = CharList { getCharList :: [Char] } deriving (Eq, Show)
```

### Type classes

```
-- Definition
class Eq a where
(==) :: a -> a -> Bool
(/=) :: a -> a -> Bool
x == y = not (x /= y) -- note the circularity here
x /= y = not (x == y) -- meaning that you only have to implement one
-- Making a type an instance of a type class
data MyStatus = Started | Stopped
instance Eq MyStatus where
Started == Started = True
Stopped == Stopped = True
_ == _ = False
-- Types can be instances of many type classes at once
instance Show MyStatus where
show Started = "Started"
show Stopped = "Stopped"
-- Defining a subclass of another typeclass
-- (in order to be an instance of `Num`, you must be an instance of `Eq`)
class (Eq a) => Num where
...
-- Parameterized types as instances of type classes
-- (works for `Mabye Int`, `Maybe Char`, `Maybe Something` etc,
-- as long as `Something` is an instance of the `Eq` typeclass)
instance (Eq m) => Eq (Maybe m) where
Just x == Just y = x == y
Nothing == Nothing = true
_ == _ = False
-- Show instances of a type class
:info Maybe
```

### Pattern matching

```
-- Multiple function definitions matching on type constructors
sumList (x:xs) = x + sumList xs
sumList [] = 0
-- Note we could also have written that last one as:
sumList _ = 0
```

### Pragmas

Enabled with `{-# LANGUAGE p1, p2... #-}`

, where `p1`

, `p2`

etc are drawn from:

`TypeSynonymInstances`

: Allow specialized polymorphic types (eg.`String`

or`[Char]`

) to be instances of a typeclass (as opposed to just`[a]`

).`OverlappingInstances`

: Given two instances that overlap (eg.`[a]`

and`[String]`

), choose the more specific one.

### Functors (`Functor`

typeclass)

Implement `fmap :: (a -> b) -> f a -> f b`

and comply with the two functor laws:

`fmap id`

must equal`id`

.`fmap (p . q)`

must equal`(fmap p) . (fmap q)`

.

In plain English, a functor is a value in a "context", supporting an `fmap`

operation for applying a function to the value while preserving that "context". The second functor law means that we can freely compose functions and apply them using `fmap`

, or compose the results of applying `fmap`

to functions, and get the same result.

Example functors:

- Lists.
- Functions.
`Maybe`

.

### Applicative functors (`Applicative`

typeclass)

These are functors where the value itself can be applied (ie. they are functions in a "context").

- Implement
`pure`

(wraps value in applicative). - Implement
`<*>`

, pronounced "apply" (`(Applicative f) => f (a -> b) -> f a -> f b`

). - Additionally,
`<$>`

, pronounced "fmap": this is an infix`fmap`

. - Note that all applicatives are functors.

Example applicative functors:

- Lists.
`Maybe`

.`Options.Applicative`

(from the optparse-applicative package).- The aeson JSON parser.

### Monoids (`Monoid`

typeclass)

- Implement a
`mappend`

binary function (`m -> m -> m`

). - The function must be associative (ie.
`(3 + 4) + 5`

is equivalent to`3 + (4 + 5)`

). - There must be an identity value (
`mempty`

) that when applied to either side of the function returns the other value unmodified. - Implement an
`mconcat`

(`[m] -> m`

) function that flattens (eg.`foldr mappend mempty`

).

Example monoids:

- Lists.
`Product`

(ie.`Num`

`newtype`

with`mempty`

:`1`

and`mappend`

:`*`

).`Sum`

(ie.`Num`

`newtype`

with`mempty`

:`0`

and`mappend`

:`+`

).`Any`

(ie.`Bool`

with`mempty`

:`False`

and`mappend`

:`||`

).`All`

(ie.`Bool`

with`mempty`

:`True`

and`mappend`

:`&&`

).`Ordering`

.`Maybe`

.

### Monads

Applicative functors (enforced by type constraint as of GHC 7.10) that additionally define `>>=`

, or "bind" (ie. `(Monad m) => m a -> (a -> m b) -> m b`

).

Example monads:

`Either`

.`Maybe`

.`Either`

.`[]`

.`IO`

.

## Other topics

### Command-line options parsing

### Parsing

- Intro to Parsing with Parsec in Haskell.
- Parsing Stuff in Haskell (video).
- Parsec: "try a <|> b" considered harmful.
- Parsing Floats With Parsec.
- Parsec Generally
- Using text.parsec.indent to Parse an Indentation-Sensitive Language with Haskell’s Parsec Library
- Power parsing with Haskell and Parsec
- Left-recursion in Parsec