Programming Languages: Appendix C:
Introduction to Haskell
Key language concepts in Haskell
 Haskell = ML + Lazy Evaluation  Side Effects.
 Haskell = LISP  Homoiconicity  Side Effects + Strong Typing + Lazy Evaluation.
 a staticallyscoped, stronglytyped, purely functional language
with a rich type system, builtin type inference algorithm, and lazy
evaluation
 named after Haskell B. Curry, the pioneer of the Ycombinator
in λcalculus.
 developed at Yale University and University of Glasgow
 descendant of Miranda
 designed to be purely functional and
thus brings programming closer to mathematics
 intended for those who want to get work done quickly and,
thus, designed to have a crisp, terse syntax;
permeates even the language's writability (e.g.,
notice no define or lambda keywords,
cons has even been reduced from cons in Scheme
to :: in ML to : in Haskell;
programmer nearly never needs to enter a ; (semicolon)
in a Haskell program)
 patterndirected invocation (pattern matching,
patternaction rule oriented style of programming)
 higherorder functions (map, ., foldl,
foldr)
 currying (curry, uncurry)
 strong typing (Haskell is a stronglytyped programming language)
 type inference (even functions have types!)
 rich and expressive type system
(ML and Haskell have arguably the most
powerful and elegant type system in all of programming languages)
 a useful generalpurpose programming language, it incorporates
 functional features from LISP,
 rulebased programming from PROLOG,
 terse syntax, and
 data abstraction from Smalltalk and C++
 Haskell is a functional language with declarative features (e.g.,
patterndirected invocation,
guards, list comprehensions, mathematical notation)
 the language pH is a parallel dialect of Haskell
Core Haskell
 simple expressions
 primitive types: Bool, Char,
String, Int (fixed precision),
Integer (arbitrary precision), Float (single
precision)
 homogeneous lists
 list operators: : (cons), ++ (append)
 higherorder functions
 functions that take functions as arguments or return a function as a value
 for instance,
map, ., foldl, foldr
 `allow common programming patterns to be encapsulated as function' [PIH],
p. 61
 can be used to define domainspecific languages
 powerful type system
 :: operator associates a type with a value or expression (e.g.,
1 :: Int)
Primitive types in Haskell
:type expression (also :t expression)
returns the type of expression
Prelude> :t 3
3 :: Num a => a
Prelude> :t 3.3
3.3 :: Fractional a => a
Prelude> :t True
True :: Bool
Prelude> :t 'a'
'a' :: Char
Prelude> :t "hello world"
"hello world" :: String
Prelude>
Essentials
 character conversions: ord and chr functions
(in Data.Char module)
 string concatenation: ++ operator
(e.g., "hello " ++ "world")
 basic arithmetic: +, , *,
/ (for reals), div (prefix; for integers) and mod
 comparison operators: ==, <, >,
<=, >=, and /=
to compare integers, reals, characters, or strings
 boolean operators: , &&, and not
 ifthenelse expressions: there is no if without an else, why?
 converting a prefix operator to infix (use backquotes or grave quotes):
div 7 2 = 7 `div` 2
mod 7 2 = 7 `mod` 2
 converting an infix operator to prefix (enclose operator in parentheses):
7 + 2 = (+) 7 2
7  2 = () 7 2
 comments:
 :? displays all available commands
 running an Haskell program
 $ ghci program.hs # from the command line
 Prelude> :load program.hs
from within the system (or :l)
 :reload (or :r) reloads the program
 : quit quits the interpreter (or use the EOF character;
on UNIX systems <crtld>)
Lists
 [] is the empty list
 lists are homogeneous (e.g., [2,3,4])
 tuples are heterogeneous (see below)
 can have lists of tuples, but each tuple in the list must
have the same type
 : is the cons operator
 takes a head (element) and a tail (list)
 x:xs is a list of at least one element
 x:[] is a list of exactly one element; same as [x]
 x:y:excess is a list of at least two elements
 x:y:nil is a list of exactly two elements
 head and tail functions (analogs of
car and cdr, respectively)
 !! selection of the nth element from a list using
zerobased indexing (e.g., [1,2,3,4,5]!!3)
 ++ is the append operator
 takes two lists
 also inefficient as in Scheme
Tuples
 can be thought of as a
heterogeneous list or struct
 idea from relational databases
 a twoelement tuple is a called a pair
 a threeelement tuple is a called a triple:
Prelude> :t (1, "Lewis", 3.76)
(1,"Lewis",3.76) :: (Fractional a, Num b) => (b,[Char],a)
Functions
 have types
 use of patterns in function arguments called patterndirected
invocation
 Haskell prints the arguments to a function
which takes >1 argument as a tuple:
add (x,y) = x+y
Main> :t add
add :: Num a => (a,a) > a
 concept of a type variable which must begin with a
lower case letter, typically a, b, and so on
 polymorphism
 concept of a class constraint, C a, where
C is the name of a class and a is a type variable:
Prelude> :t (+)
(+) :: Num a => a > a > a
Prelude>
Some userdefined functions
function, parameter, and value names must begin with a lower case letter
{
simple functions
patterndirected invocation
pattern matching
like cases in Scheme
}
square (x) = x*x
fact (0) = 1
fact (n) = n * fact (n1)
fact (n) = product [1..n]
sumlist ([]) = 0
sumlist (x:xs) = x + sumlist (xs)
fib (0) = 1
fib (1) = 1
fib (n) = fib (n1) + fib(n2)
 gcd is built in Prelude.hs
gcd1 (u, 0) = u
gcd1 (u, v) = gcd1 (v, (mod u v))
gcd1 (u, v) = if v == 0 then u else gcd1 (v, (mod u v))
 with patterndirected invocation
 reverse is builtin Prelude.hs
reverse1 [] = []
reverse1 (h:t) = reverse1 (t ++ [h])
 without patterndirected invocation need a head and tail,
 or an ifthenelse and hd and tl;
 head and tail are the analogs of car and cdr, respectively
reverse2 ([]) = ([])
reverse2 (lst) = reverse2(tail(lst)) ++ [head(lst)]
reverse3 (lst) =
if lst == [] then []
else reverse3 (tail(lst)) ++ [head(lst)]
reverse4 lst@(x:xs) =
if lst == [] then [] else reverse4 xs ++ [x]
 inspired by pp. 8488 of [EMPL];
 use difference lists technique
rev1 ([], m) = m
rev1 ((x:xs), ys) = rev1 (xs, (x:ys))
reverse5 (lst) = rev1 (lst, [])
 elem is the Haskell member function in Prelude.hs
member (_, []) = False
member (e, (x:xs)) = (x == e)  member (e, xs)
insertineach (_, []) = []
insertineach (item, (x:xs)) = (item:x):insertineach(item, xs)
 notice how use of "let"
 prevents recomputation
powerset ([]) = [[]]
powerset (x:xs) =
let
temp = powerset (xs)
in
(insertineach (x, temp)) ++ temp
 can be similarly written with where
{
powerset ([]) = [[]]
powerset (x:xs) = (insertineach (x, temp)) ++ temp
where temp = powerset (xs)
}
Mergesort
split ([]) = ([], [])
split ([x]) = ([], [x])
split (x:y:excess) =
let
(left, right) = split(excess)
in
(x:left, y:right)
merge (lst, []) = lst
merge ([], lst) = lst
merge (left@(l:ls), right@(r:rs)) =
if l < r then l:(merge (ls, right))
else r:(merge (left, rs))
if l < r then l:(merge (ls, (r:rs)))
else r:(merge ((l:ls), rs))
mergesort ([]) = []
mergesort ([x]) = [x]
mergesort (lst) =
let
 split it
(left, right) = split (lst)
 mergesort each side
leftsorted = mergesort (left)
rightsorted = mergesort (right)
in
 merge
merge (leftsorted, rightsorted)
 alternatively
{
mergesort ([]) = []
mergesort ([x]) = [x]
mergesort (lst) =
 merge
merge (leftsorted, rightsorted)
where
 split it
(left, right) = split (lst)
 mergesort each side
leftsorted = mergesort (left)
rightsorted = mergesort (right)
}
Anonymous or literal functions
(\n > n+1) (5)
addtwo n = n + 2
map addtwo [1,2,3]
map (\n > n+2) [1,2,3]
why use an anonymous function? see definition of string2int
Monads: sideeffectfree I/O
An extension of the idea of potentially infinite data structures
or streams made possible through lazy evaluation.
Monad takes its name from a branch of mathematics known
as category theory.
