Haskell

GHCi

  • :reload reload all names in scope

  • :quit

  • :t 9 returns the type of 9

  • :info [] returns lots of useful details about the implemented typeclasses

  • :k Int returns the kind of Int

  • :set prompt "\x03BB > " would change the command prompt to λ >

  • :set -XExistentialQuantification sets up the language extension

You can give multiline input to GHCi as follows:

*Main> :{
*Main| let askname = do
*Main| putStrLn "What is your name?"
*Main| name <- getLine
*Main| putStrLn $ "Hello " ++ name
*Main| :}
*Main>

General syntax

Quick reference:

The best way to find out about these kind of constructs in ghci, e.g. :info <*>:

  • (.) - Function composition

  • <*>

  • $

Guard syntax

Guard Syntax allows us to conditionally check a statement within a pattern matching expression.

describeLetter :: Char -> String
describeLetter c
| c >= 'a' && c <= 'z' = "Lower case"
| c >= 'A' && c <= 'Z' = "Upper case"
| otherwise = "Not an ASCII letter"

'where' clause

Define inline bindings (e.g. to functions or values). The following example uses guards and a where clase:

bmiTell :: (RealFloat a) => a -> a -> String
bmiTell weight height
| bmi <= 18.5 = "You're underweight, you emo, you!"
| bmi <= 25.0 = "You're supposedly normal. Pffft, I bet you're ugly!"
| bmi <= 30.0 = "You're fat! Lose some weight, fatty!"
| otherwise = "You're a whale, congratulations!"
where bmi = weight / height ^ 2

'as' Pattern

The 'as' pattern (described here, here and here), gives us a way of matching a name for the entire element being pattern matched in a list:

The following would be read all as (x:xs):

capital :: String -> String
capital "" = "Empty string, whoops!"
capital all@(x:xs) = "The first letter of " ++ all ++ " is " ++ [x]

Modules

This page from 'Learn you a Haskell' is a good reference.

  • Import hiding

import Data.List hiding (nub)

Indentation

From this page, the golden rule of indentation is:

Code which is part of some expression should be indented further in than the beginning of that expression...All grouped expressions must be exactly aligned

But you can avoid indentation:

Indentation is actually optional if you instead use semicolons and curly braces

Types and Typeclasses

In the following snippet (reference):

  • data means we're declaring a new type

  • Expr is the type constructor

  • I ..., Add ..., Mul ... are the value constructors

data Expr = I Int -- integer constants
| Add Expr Expr -- add two expressions
| Mul Expr Expr -- multiply two expressions
  • Adding deriving (Show) at the end of a data declaration automatically makes that type part of the Show typeclass (reference):

data Expr = I Int -- integer constants
| Add Expr Expr -- add two expressions
| Mul Expr Expr -- multiply two expressions
deriving (Show)

Record syntax declarations

Syntactic sugar providing data accessors:

data Configuration = Configuration
{ username :: String
, localHost :: String
, remoteHost :: String
, isGuest :: Bool
, isSuperuser :: Bool
, currentDir :: String
, homeDir :: String
, timeConnected :: Integer
}

You can pattern match against them:

getHostData (Configuration { localHost = lh, remoteHost = rh }) = (lh, rh)

And create new versions with certain fields overwritten using:

cfg { currentDir = newDir }

newtype declarations

For the moment, I treat newtype as being broadly interchangable with data when creating a new type. There's documentation about it here.

Typeclass: Semigroup

A set with an associative binary operation. Superset of Monoids.

Typeclass: Monoids

Monoid is a typeclass with an associative mappend operation and an identity element.

Integer numbers form a monoid under addition with 0 as identity element Integer numbers form a monoid under multiplication with 1 as identity element Lists form a monoid under concatenation with the empty list as identity element

mappend is given the infix synonym (<>)

Generalised Algebraic Datatypes (GADTs)

The crux of GADTs is that the provide a way to explicitly declare the type signature of each constructor.

The following language option is required:

{-#LANGUAGE GADTs #-}

And then an example would be:

data Maybe a where
Nothing :: Maybe a
Just :: a -> Maybe a

Miscellaneous

Template Haskell

Template Haskell is similar to Lisp macros.

{-# LANGUAGE TemplateHaskell #-}

It is used e.g. by lens to generate the various lenses into data structures at compile time

Forall Keyword

forall imposes constraints on parameterising types when defining new data types