Sie sind auf Seite 1von 75

Preliminaries

A Quick Dip into Haskell

Fancy Types

Rich Libraries

Practical Tools

::

HASKELL
Pure Functional Programming
February 12, 2014

Levi Pearson

Preliminaries

A Quick Dip into Haskell

Fancy Types

Rich Libraries

Practical Tools

Preliminaries

Preliminaries

A Quick Dip into Haskell

Fancy Types

Rich Libraries

Practical Tools

FUNCTIONAL PROGRAMMING?

What is functional programming? What makes it different?

Functions are close to the mathematical concept


Programs are built (mainly) from functions, not statements
Functions are first-class data

Preliminaries

A Quick Dip into Haskell

Fancy Types

Rich Libraries

Practical Tools

FUNCTIONAL DIFFERENCES

What makes functional programming different?

No side effects
Order of evaluation is less significant
Equational reasoning

Preliminaries

A Quick Dip into Haskell

Fancy Types

Rich Libraries

Practical Tools

FUNCTIONAL POWER

But where is the real power of functional programming?

Is denying ourselves effects and assignment really it?


What makes functional programming powerful?
More tools for modularity!

Why Functional Programming Matters - John Hughes (1984)


http://www.cse.chalmers.se/~rjmh/Papers/whyfp.pdf

Preliminaries

A Quick Dip into Haskell

Fancy Types

Rich Libraries

Practical Tools

MODULARITY THROUGH HIGHER-ORDER FUNCTIONS

Functional programs capture patterns of computation

Data gives rise to general processing functions


General functions do work with function arguments
Functions are compositional

Preliminaries

A Quick Dip into Haskell

Fancy Types

Rich Libraries

Practical Tools

LAZINESS AND COMPOSITION

Lazy evaluation leads to better modularity

Laziness allows interleaving of processing


Amortized-cost data structures
Forces honesty about functional purity!

Preliminaries

A Quick Dip into Haskell

Fancy Types

Rich Libraries

Practical Tools

RICH STATIC TYPES


Types express important properties of programs

A type can be thought of as the set of values that belong to it


Functions are values, too, and belong to function types
Different type systems provide different ways to classify
values
Type checking ensures that properties required by evaluation
are met

Preliminaries

A Quick Dip into Haskell

Fancy Types

Rich Libraries

Practical Tools

RICH STATIC TYPES


Types express important properties of programs

A type can be thought of as the set of values that belong to it


Functions are values, too, and belong to function types
Different type systems provide different ways to classify
values
Type checking ensures that properties required by evaluation
are met
Well-typed programs can't go wrong

A Theory of Type Polymorphism in Programming - Robin Milner


(1978)
http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.67.5276
8

Preliminaries

A Quick Dip into Haskell

Fancy Types

Rich Libraries

Practical Tools

A Quick Dip into Haskell

Preliminaries

A Quick Dip into Haskell

Fancy Types

Rich Libraries

Practical Tools

AN OBLIGATORY EXAMPLE

The Fibonnaci numbers -- all of them!


fibs :: [Integer]
fibs = 1 : 1 : zipWith (+) fibs (tail fibs)
fib :: Int -> Integer
fib = (fibs !!)

10

Preliminaries

A Quick Dip into Haskell

Fancy Types

Rich Libraries

Practical Tools

LAZY EVALUATION

Let's step through an evaluation of fib:


fibs = ...
fib 4
We have bound fibs to an expression, but it is unevaluated

11

Preliminaries

A Quick Dip into Haskell

Fancy Types

Rich Libraries

Practical Tools

fibs = ...
fib 4
Substitute the definition of fib:
fib = (fibs !!)
Giving:
fibs = ...
fibs !! 4

12

Preliminaries

A Quick Dip into Haskell

Fancy Types

Rich Libraries

Practical Tools

fibs = ...
fibs !! 4
The !! operator is just a function:
fibs = ...
(!!) fibs 4
In a strict (applicative order) language, we would fully evaluate
fibs now and fall into infinite recursion. In Haskell, we evaluate
(!!) instead!

13

Preliminaries

A Quick Dip into Haskell

Fancy Types

Rich Libraries

Practical Tools

We'll need some definitions from the Prelude:


-- simplified definition of (!!)
(!!) (x:_) 0 = x
(!!) (_:xs) n = (!!) xs (n-1)
-- simplified definition of zipWith
zipWith f (a:as) (b:bs) = f a b : zipWith as bs
Note that we can define operators as functions named with
non-alphanumeric characters.
We can also use regular named functions as operators by
enclosing them in backticks.

14

Preliminaries

A Quick Dip into Haskell

Fancy Types

Rich Libraries

Practical Tools

-- simplified definition of (!!)


(!!) (x:_) 0 = x
-- no match
(!!) (_:xs) n = (!!) xs (n-1) -- match!
Case analysis, i.e. examining data, forces evaluation, but only to
the next data constructor!
fibs = 1 : ...
let _
xs
n
in
(!!)

= 1
= ...
= 4
xs 3

15

Preliminaries

A Quick Dip into Haskell

Fancy Types

Rich Libraries

Practical Tools

-- simplified definition of (!!)


(!!) (x:_) 0 = x
-- no match
(!!) (_:xs) n = (!!) xs (n-1) -- match!
Another round, and another evaluation of fibs is forced.
fibs = 1 : 1 : ...
let _
xs
n
in
(!!)

= 1
= ...
= 3
xs 2

16

Preliminaries

A Quick Dip into Haskell

Fancy Types

Rich Libraries

Practical Tools

-- simplified definition of (!!)


(!!) (x:_) 0 = x
-- no match
(!!) (_:xs) n = (!!) xs (n-1) -- match!
We exhausted the simple conses; zipWith is revealed and must be
evaluated before we can evaluate xs !! 3
fibs = 1 : 1 : zipWith (+) fibs (tail fibs)
let x
xs
n
in
(!!)

= 1
= zipWith (+) fibs (tail fibs)
= 3
xs 2

17

Preliminaries

A Quick Dip into Haskell

Fancy Types

Rich Libraries

Practical Tools

-- simplified definition of zipWith


zipWith f (a:as) (b:bs) = f a b : zipWith f as bs
Again we evaluate the outer function before its parameters:
fibs = 1 : 1 : zipWith (+) fibs (tail fibs)
let f
= (+)
(a:as) = fibs
(b:bs) = tail fibs
in
f a b : zipWith f as bs

18

Preliminaries

A Quick Dip into Haskell

Fancy Types

Rich Libraries

Practical Tools

fibs = 1 : 1 : zipWith (+) fibs (tail fibs)


let f
= (+)
(a:as) = fibs
(b:bs) = tail fibs
in
f a b : zipWith f as bs
We must examine both fibs and tail fibs, but fortunately we
have already evaluated them! (At least to their first data
constructors)
fibs = 1 : 1 : zipWith (+) fibs (tail fibs)
let f
= (+)
(a:as) = 1 : 1 : ...
(b:bs) = 1 : ...
in
f a b : zipWith f as bs
19

Preliminaries

A Quick Dip into Haskell

Fancy Types

Rich Libraries

Practical Tools

fibs = 1 : 1 : zipWith (+) fibs (tail fibs)


let f
= (+)
(a:as) = 1 : 1 : ...
(b:bs) = 1 : ...
in
f a b : zipWith f as bs
Now we perform substitutions. f a b becomes (1 + 1)
fibs = 1 : 1 : zipWith (+) fibs (tail fibs)
let as
= 1 : ...
bs
= ...
in
(1 + 1) : zipWith (+) as bs
20

Preliminaries

A Quick Dip into Haskell

Fancy Types

Rich Libraries

Practical Tools

-- simplified definition of (!!)


(!!) (x:_) 0 = x
-- no match
(!!) (_:xs) n = (!!) xs (n-1) -- match!
Now we can make progress with !! again. We don't examine the
sum; it never gets evaluated.
fibs = 1 : 1 : (1 + 1) : zipWith (+) as bs
let _
xs
n
in
(!!)

= (1 + 1)
= zipWith (+) as bs
= 2
xs 1

But the next step of !! needs to examine xs


21

Preliminaries

A Quick Dip into Haskell

Fancy Types

Rich Libraries

Practical Tools

-- simplified definition of zipWith


zipWith f (a:as) (b:bs) = f a b : zipWith f as bs
Once again we step through our two lists; really the same list at
two positions.
fibs = 1 : 1 : (1 + 1) : zipWith (+) as bs
let f
a
as
b
bs
in
1 + (1 +

=
=
=
=
=

(+)
1
(1 + 1) : ...
(1 + 1)
...

1) : zipWith (+) as bs

22

Preliminaries

A Quick Dip into Haskell

Fancy Types

Rich Libraries

Practical Tools

-- simplified definition of (!!)


(!!) (x:_) 0 = x
-- no match
(!!) (_:xs) n = (!!) xs (n-1) -- match!
We consume what we just generated again
fibs = 1 : 1 : (1 + 1) : (1 + (1 + 1)) : zipWith (+) as bs
let _
xs
n
in
(!!)

= (1 + (1 + 1))
= zipWith (+) as bs
= 1
xs 0

23

Preliminaries

A Quick Dip into Haskell

Fancy Types

Rich Libraries

Practical Tools

-- simplified definition of zipWith


zipWith f (a:as) (b:bs) = f a b : zipWith f as bs
The next zipWith evaluation gives us the list constructor with the
expression we're looking for at its head.
fibs = 1 : 1 : (1 + 1) : (1 + (1 + 1)) : ((1 + 1) + (1 + (1 +
let f
as
bs
in
((1 + 1)

= (+)
= (1 + (1 + 1)) : ...
= ...
+ (1 + (1 + 1)) : zipWith (+) as bs

24

Preliminaries

A Quick Dip into Haskell

Fancy Types

Rich Libraries

Practical Tools

-- simplified definition of (!!)


(!!) (x:_) 0 = x
-- match!
(!!) (_:xs) n = (!!) xs (n-1) -- ignored
We finally hit the base case of our recursion! We still have not
done a case analysis on x, though, so the expression is not
evaluated yet.
fibs = 1 : 1 : (1 + 1) : (1 + (1 + 1)) : ((1 + 1) + (1 + (1 +
let x = ((1 + 1) + (1 + (1 + 1))
_ = ...
in
((1 + 1) + (1 + (1 + 1))

25

Preliminaries

A Quick Dip into Haskell

Fancy Types

Rich Libraries

Practical Tools

Assuming we display the resulting expression, it will finally be


evaluated along with its sub-expressions, which were really
references to earlier list elements.
fibs = 1 : 1 : 2 : 3 : 5 : ...
5
Future calls of fib 0 through fib 4 will just be simple list index
operations.

26

Preliminaries

A Quick Dip into Haskell

Fancy Types

Rich Libraries

Practical Tools

ADVANTAGES OF LAZINESS

If any order of evaluation will reduce to a solution, lazy


evaluation will reduce to a solution.
Many programs in this compositional style lead to
non-terminating loops in strictly-evaluated languages
As a result, programmers in strict functional languages end
up writing a lot of low-level recursive functions
Laziness is necessary for many efficient functional data
structures (but optional laziness in an otherwise strict
language can provide enough for this)

http://www.cs.cmu.edu/~rwh/theses/okasaki.pdf
http://www.amazon.com/Purely-Functional-Structures-ChrisOkasaki/dp/0521663504
http://okasaki.blogspot.com/2008/02/ten-years-of-purelyfunctional-data.html
27

Preliminaries

A Quick Dip into Haskell

Fancy Types

Rich Libraries

Practical Tools

COSTS OF LAZINESS

It is no longer obvious when any piece of code will evaluate

Side-effects would be intractable to reason about, so


functions must be pure

Managing unevaluated expressions has both space and time


costs which are sometimes difficult to reason about.

Haskell provides some optimizations and optional strictness


features that can alleviate some of these problems, but it
takes experience to learn how to use them well

28

Preliminaries

A Quick Dip into Haskell

Fancy Types

Rich Libraries

Practical Tools

LAZINESS + PURITY + FANCY TYPES = HASKELL

Haskell is the only functional language in common use that


does non-strict evaluation by default

Because of lazy evaluation, Haskell has had no choice but to


make all functions pure

This ``hair shirt'' of lazy evaluation has led to many


interesting advancements in functional programming

29

Preliminaries

A Quick Dip into Haskell

Fancy Types

Rich Libraries

Practical Tools

Fancy Types

30

Preliminaries

A Quick Dip into Haskell

Fancy Types

Rich Libraries

Practical Tools

ALGEBRAIC DATA
Lists are supported with special syntax, but you can build an
equivalent type with a data declaration:
data List a = Cons a (List a)
| Nil
This means: For all types a, we can form a List a value by
supplying the constructor Cons with a value of type a and another
value of type List a, or by using the constructor Nil.

List is parameterized by a; it is polymorphic in a


List is a recursive type because it can contain members of
its own type

-- Equivalent to [1, 2, 3] or 1 : 2 : 3 : []
sugarFreeList = Cons 1 (Cons 2 (Cons 3 Nil))
31

Preliminaries

A Quick Dip into Haskell

Fancy Types

Rich Libraries

Practical Tools

SUMS AND PRODUCTS


If we view a type as a set of values, we can combine those sets to
form new types in two ways:

Product types are essentially tuples. In the set view, a pair


of two types would contain the set of the cross product of its
member types
Each value of a sum type contains only one of two or more
alternative types, but it is paired with a tag value to
distinguish which alternative it comes from. In set parlance,
a disjoint union

data List a = Cons a (List a)


| Nil
List is the sum of a product (A L(A)) and a unit type (1), so
algebraically it is: L(A) = A L(A) + 1
32

Preliminaries

A Quick Dip into Haskell

Fancy Types

Rich Libraries

Practical Tools

NTH DERIVATIVE IS THE N-HOLE CONTEXT


Consider the type (Int, Int, Int).
It is a product type, A A A, or A3 .
We would like to transform a value of this type, such as (1, 2, 3),
by exchanging one value.
We could poke a hole in the data structure to make room for the
new value and keep track of where it should go. This new data
structure forms a one-hole context in which to place a value to
get back the original.
(_, 2, 3)
(1, _, 3)
(1, 2, _)

33

Preliminaries

A Quick Dip into Haskell

Fancy Types

Rich Libraries

Practical Tools

NTH DERIVATIVE IS THE N-HOLE CONTEXT (CONT)


There are now three alternatives, each of which has a pair of
integers. We represent alternatives as a sum type:
data OneHoleTriple = First (Int, Int)
| Second (Int, Int)
| Third (Int, Int)

34

Preliminaries

A Quick Dip into Haskell

Fancy Types

Rich Libraries

Practical Tools

NTH DERIVATIVE IS THE N-HOLE CONTEXT (CONT)


There are now three alternatives, each of which has a pair of
integers. We represent alternatives as a sum type:
data OneHoleTriple = First (Int, Int)
| Second (Int, Int)
| Third (Int, Int)
A A + A A + A A, or more succinctly: 3A2

34

Preliminaries

A Quick Dip into Haskell

Fancy Types

Rich Libraries

Practical Tools

NTH DERIVATIVE IS THE N-HOLE CONTEXT (CONT)


There are now three alternatives, each of which has a pair of
integers. We represent alternatives as a sum type:
data OneHoleTriple = First (Int, Int)
| Second (Int, Int)
| Third (Int, Int)
A A + A A + A A, or more succinctly: 3A2
d 3
A = 3A2
dA

34

Preliminaries

A Quick Dip into Haskell

Fancy Types

Rich Libraries

Practical Tools

NTH DERIVATIVE IS THE N-HOLE CONTEXT (CONT)


There are now three alternatives, each of which has a pair of
integers. We represent alternatives as a sum type:
data OneHoleTriple = First (Int, Int)
| Second (Int, Int)
| Third (Int, Int)
A A + A A + A A, or more succinctly: 3A2
d 3
A = 3A2
dA
The derivative of a data type is the type of its one-hole context!
The Derivative of a Regular Type is its Type of One-Hole Contexts
- Conor McBride (2001)
http://strictlypositive.org/diff.pdf
34

Preliminaries

A Quick Dip into Haskell

Fancy Types

Rich Libraries

Practical Tools

PARAMETRICITY
In Haskell type signatures, type variables are implicitly
universally quantified.

Universal quantification means that the function must make


the same mapping for all possible types in that position.
In other words, the function may not examine or otherwise
depend on the type of values it operates on! It has a single
implementation that works uniformly on all types.

Fundamental Concepts in Programming Languages - Christopher


Strachey (1967)
http://www.itu.dk/courses/BPRD/E2009/fundamental-1967.pdf

35

Preliminaries

A Quick Dip into Haskell

Fancy Types

Rich Libraries

Practical Tools

PARAMETRICITY
In Haskell type signatures, type variables are implicitly
universally quantified.

Universal quantification means that the function must make


the same mapping for all possible types in that position.
In other words, the function may not examine or otherwise
depend on the type of values it operates on! It has a single
implementation that works uniformly on all types.

Fundamental Concepts in Programming Languages - Christopher


Strachey (1967)
http://www.itu.dk/courses/BPRD/E2009/fundamental-1967.pdf
f :: a -> a

What does this signature tell us about f?


How many sensible functions inhabit this type?
35

Preliminaries

A Quick Dip into Haskell

Fancy Types

Rich Libraries

Practical Tools

PARAMETRIC REASONING
Parametricity places restrictions on a (pure, total) function's
behavior that can provide powerful tools for reasoning.
f :: (a -> Bool) -> [a] -> [a]

36

Preliminaries

A Quick Dip into Haskell

Fancy Types

Rich Libraries

Practical Tools

PARAMETRIC REASONING
Parametricity places restrictions on a (pure, total) function's
behavior that can provide powerful tools for reasoning.
f :: (a -> Bool) -> [a] -> [a]
f takes a function a to Bool and a list of a, then returns a list of a

36

Preliminaries

A Quick Dip into Haskell

Fancy Types

Rich Libraries

Practical Tools

PARAMETRIC REASONING
Parametricity places restrictions on a (pure, total) function's
behavior that can provide powerful tools for reasoning.
f :: (a -> Bool) -> [a] -> [a]
f takes a function a to Bool and a list of a, then returns a list of a

The output list's elements may only come from the input list
Which elements from the input, which order, and how many
of each may only vary based on the predicate and the input
The decision may only inspect the length of the input list and
apply the predicate to its elements

Types, Abstraction, and Parametric Polymorphism - John


Reynolds (1983)
http://www.cse.chalmers.se/edu/year/2010/course/DAT140_Types/Reyn
Theorems for Free! - Philip Wadler (1989)
http://citeseer.ist.psu.edu/viewdoc/summary?doi=10.1.1.38.9875

36

Preliminaries

A Quick Dip into Haskell

Fancy Types

Rich Libraries

Practical Tools

TYPE CLASSES
What type should we give the following function?
(+) :: ? -> ? -> ?

37

Preliminaries

A Quick Dip into Haskell

Fancy Types

Rich Libraries

Practical Tools

TYPE CLASSES
What type should we give the following function?
(+) :: ? -> ? -> ?
(+) :: Integer -> Integer -> Integer
This would require a different operator for Float addition. . . .
(+) :: a -> a -> a
This won't work due to parametricity.

37

Preliminaries

A Quick Dip into Haskell

Fancy Types

Rich Libraries

Practical Tools

TYPE CLASSES
What type should we give the following function?
(+) :: ? -> ? -> ?
(+) :: Integer -> Integer -> Integer
This would require a different operator for Float addition. . . .
(+) :: a -> a -> a
This won't work due to parametricity.
(+) :: Num a => a -> a -> a
Bounded polymorphism constrains parametricity with a predicate:
``For all types a for which Num a holds, take an a and another a and
return an a as the result.''
37

Preliminaries

A Quick Dip into Haskell

Fancy Types

Rich Libraries

Practical Tools

TYPE CLASS INSTANCES


Class instances satisfy class constraint predicates:
instance Num Integer where ...
instance Num Float where ...

Instances describe all the type-specific behavior of the class


An instance is given as a set of functions that may be used in
expressions that have the type class constraint
Dispatch is type-based, not value-based
The constrained type variable may occur at any position in
the signature, including return types!
The class constraint can be viewed as an extra parameter
through which the correct instance is supplied as a dictionary

How To Make Ad-Hoc Polymorphism Less Ad-Hoc - Wadler; Blott


(1989)
http://homepages.inf.ed.ac.uk/wadler/papers/class/class.ps
38

Preliminaries

A Quick Dip into Haskell

Fancy Types

Rich Libraries

Practical Tools

COMMON TYPE CLASSES

Show: Instances are convertible to strings


Read: Instances are convertible from strings
Eq: Instances may be compared for equality
Ord: Instances have a total ordering
Enum: Instances may be sequentially enumerated
Bounded: Instances have an upper and lower bound
Num: Instances support + and * (form a ring)
Real, Fractional, Integral: Specific varieties of numbers
Functor, Monad, MonadPlus: Instances are warm and fuzzy!

Haskell can auto-derive correct instances of Show through


Bounded
Typeclassopedia - Brent Yorgey (2009)
http://www.haskell.org/haskellwiki/Typeclassopedia
39

Preliminaries

A Quick Dip into Haskell

Fancy Types

Rich Libraries

Practical Tools

KINDS

In Haskell, values are classified by types; types are classified by


kinds.

Ordinary types are of kind *


Type constructors are of kind * -> *

For example:
Int :: *
a -> a :: *
[] :: * -> *
(->) :: * -> * -> *

40

Preliminaries

A Quick Dip into Haskell

Fancy Types

Rich Libraries

Practical Tools

CONSTRUCTOR CLASSES
The class constraint mechanism applies to more than ordinary
types

Type classes like Num and Show apply to types of kind *


Functor, Monad, and MonadPlus apply to kind * -> *
Since * -> * is the kind of type constructors (types that take
type-level parameters), classes on types of that kind are
sometimes called ``constructor classes''

For example, the list type ([]) is a type constructor.

It constructs from any type a the type of lists of a


It is a member of (has an instance defined for) Functor,
Monad, and MonadPlus.

A System of Constructor Classes: Overloading and Implicit


Higher-Order Polymorphism - Mark P Jones (1993)
http://web.cecs.pdx.edu/~mpj/pubs/fpca93.html

41

Preliminaries

A Quick Dip into Haskell

Fancy Types

Rich Libraries

Practical Tools

FUN FACTS ABOUT LISTS

Some interesting properties of lists that you may know:

Operations can be applied to the whole list at once:


map (+ 1) [1, 2, 3] ==> [2, 3, 4]

Mapping the identify function over a list returns the same list:
map id [1, 2, 3] ==> [1, 2, 3]

Composing before or after mapping makes no difference:


map (+ 1) . map (* 2) == map ( (+ 1) . (* 2) )

42

Preliminaries

A Quick Dip into Haskell

Fancy Types

Rich Libraries

Practical Tools

LISTS ARE FUNCTORS

These actually hold for any type constructor F :: * -> *:

A ``lifting'' operation that makes an operation on the base


type apply evenly to the constructed type:
fmap :: (a -> b) -> F a -> F b

Lifting preserves identity:


fmap id == id

Lifting respects composition:


fmap g . fmap f == fmap (g . f)

These properties can be implemented uniquely for any type


constructor.

43

Preliminaries

A Quick Dip into Haskell

Fancy Types

Rich Libraries

Practical Tools

SO WHAT?

Given the Functor class, we have a uniform way of lifting ordinary


functions into new contexts.

The mechanism for doing this doesn't depend on the specific


types; the compiler works out the correct instance via the
context

The lifted operations compose nicely just like their un-lifted


counterparts did.

This is the essence of functional programming abstraction!

44

Preliminaries

A Quick Dip into Haskell

Fancy Types

Rich Libraries

Practical Tools

ANOTHER USEFUL FUNCTOR

This type can be used to safely represent the idea of a partial


function
data Maybe a = Just a
| Nothing
instance Functor Maybe where
fmap f Nothing = Nothing
fmap f (Just x) = f x

45

Preliminaries

A Quick Dip into Haskell

Fancy Types

Rich Libraries

Practical Tools

AVOIDING AWKWARDNESS
We have two functions, f and g, that we would like to compose:
f :: b -> c
g :: a -> Maybe b
We can solve this problem by lifting f to the Maybe Functor:
(fmap f)
g

:: Maybe b -> Maybe c


:: a
-> Maybe b

(fmap f) . g :: a

-> Maybe c

Using Functor (and Monad) methods we can usually collapse


repeated error checks to a single one.
46

Preliminaries

A Quick Dip into Haskell

Fancy Types

Rich Libraries

Practical Tools

Rich Libraries

47

Preliminaries

A Quick Dip into Haskell

Fancy Types

Rich Libraries

Practical Tools

PRELUDE

Imported by default into every module

Basic types, type classes, and functions


Contents defined by the Haskell Report:
http://www.haskell.org/definition/

48

Preliminaries

A Quick Dip into Haskell

Fancy Types

Rich Libraries

Practical Tools

BASE
Standard libraries that ship with GHC, including Prelude.

Control hierarchy: Data types and functions that primarily


provide control flow management

Data hierarchy: Data types and functions for managing data;


expanded functionality on Prelude types plus some extra
goodies like Data.Foldable, Data.Traversable, Data.Monoid,
etc.

Debug.Trace: Who says you can't printf debug in haskell?

Foreign hierarchy: Interface with C functions

System hierarchy: Interface with the OS

GHC hierarchy: The compiler, as a library

http://hackage.haskell.org/package/base
49

Preliminaries

A Quick Dip into Haskell

Fancy Types

Rich Libraries

Practical Tools

CONTAINERS / UNORDERED-CONTAINERS

containers provides efficient immutable implementations of


graphs, sets, maps, general sequences, and trees.
http://hackage.haskell.org/package/containers

unordered-containers provides efficient hashing-based


containers, both a HashMap and HashSet.
http://hackage.haskell.org/package/unordered-containers

50

Preliminaries

A Quick Dip into Haskell

Fancy Types

Rich Libraries

Practical Tools

BYTESTRING / TEXT
The Prelude's String is defined as:
type String = [Char]
This is convenient, but not fast.

bytestring provides an efficient, compact, immutable string


type that can hold binary or 8-bit character data.
Strict bytestrings are stored in a single large array.
Lazy bytestrings are stored in a lazy list of strict chunks;
perfect for I/O streaming
text is primarily concerned with correct handling of different
textual encodings.
Both provide all of the Prelude list operations that make
sense, so it is easy to switch to one of these if you start with
String.

http://hackage.haskell.org/package/bytestring

51

Preliminaries

A Quick Dip into Haskell

Fancy Types

Rich Libraries

Practical Tools

NETWORK

Efficient sockets implementation, including integration with


bytestring
http://hackage.haskell.org/package/network

52

Preliminaries

A Quick Dip into Haskell

Fancy Types

Rich Libraries

Practical Tools

PARSEC: MONADIC PARSING COMBINATORS


csvFile = endBy line eol
line = sepBy cell (char ',')
cell = quotedCell <|> many (noneOf ",\n\r")
quotedCell = do char '"'
content <- many quotedChar
char '"' <?> "quote at end of cell"
return content
quotedChar = noneOf "\""
<|> try (string "\"\"" >> return '"')
eol =
try (string "\n\r") <|> try (string "\r\n")
<|> string "\n"
<|> string "\r" <?> "end of line"
parseCSV input = parse csvFile "(unknown)" input
Parsec: Direct-Style Parsing Combinators for the Real World Daan Leijen (2001)
http://research.microsoft.com/enus/um/people/daan/download/papers/parsec-paper.pdf

53

Preliminaries

A Quick Dip into Haskell

Fancy Types

Rich Libraries

Practical Tools

BINARY

The Data.Binary hierarchy provides translation between types


and binary representations

Primitives for reading and writing variously sized chunks at a


time
Byte-order conversion
Provides Get and Put type classes to give a uniform interface
to serialization
Automatic serialization if you don't care about representation
Custom serialization if you do

http://hackage.haskell.org/package/binary

54

Preliminaries

A Quick Dip into Haskell

Fancy Types

Rich Libraries

Practical Tools

STM

Software Transactional Memory

Shared memory between threads


Provides a monadic interface for atomic transactions
Deadlock-free and easy to use
Not as fast as more complex solutions, but also not likely to
bite you

Composable Memory Transactions Tim Harris, Simon Marlow, Simon Peyton Jones, and Maurice
Herlihy (2005)
http://research.microsoft.com/Users/simonpj/papers/stm/index.htm

55

Preliminaries

A Quick Dip into Haskell

Fancy Types

Rich Libraries

Practical Tools

AESON

Efficient JSON serialization

Map Haskell types directly to JSON representations


Derive the serialization automatically, or write custom ones
Provides a handy set of types for working directly with JSON
as well

http://hackage.haskell.org/package/aeson

56

Preliminaries

A Quick Dip into Haskell

Fancy Types

Rich Libraries

Practical Tools

PIPES / CONDUIT

Efficient streaming libraries

Guarantee constant memory footprint via chunking of data


Deterministic resource handling
Streams are created, transformed, and consumed by
composable components
Many adapters provide facilities for parsing, encryption,
compression, protocol handling, serialization, etc.

http://hackage.haskell.org/package/pipes
http://hackage.haskell.org/package/conduit

57

Preliminaries

A Quick Dip into Haskell

Fancy Types

Rich Libraries

Practical Tools

LENS

Generalized Getter/Setter Framework

Provides a query language for data structures, including


deeply nested ones, that can find and update specific values
Includes a library of operators that resemble similar
operators in OO languages.

http://hackage.haskell.org/package/lens
https://github.com/ekmett/lens/wiki
http://skillsmatter.com/podcast/scala/lenses-compositionaldata-access-and-manipulation

58

Preliminaries

A Quick Dip into Haskell

Fancy Types

Rich Libraries

Practical Tools

Practical Tools

59

Preliminaries

A Quick Dip into Haskell

Fancy Types

Rich Libraries

Practical Tools

GHC

The Glorious Glasgow Haskell Compiler

Compiler
Interactive interpreter
Integrated build system and library management
Highly optimizing, with user-definable rewrite rules
Standards-compliant by default, but supports many fancy
extensions

https://www.haskell.org/ghc/

60

Preliminaries

A Quick Dip into Haskell

Fancy Types

Rich Libraries

Practical Tools

CABAL

A framework for building and packaging Haskell code

Packages are defined via a declarative language describing


versioned dependencies, code entry point, automated tests,
etc.
The cabal-install application can download Haskell
libraries and applications from a central repository
Recent versions of cabal support sandboxed environments to
avoid dependency problems

http://www.haskell.org/cabal/

61

Preliminaries

A Quick Dip into Haskell

Fancy Types

Rich Libraries

Practical Tools

HADDOCK

An inline documentation format for Haskell source files.

Like Javadoc, Doxygen, etc. in applying specially formatted


comments to auto-generated documentation of code
structure
Supports a lightweight markup format for structuring longer
documentation, providing examples, and hyperlinking
references to other documentation.
Integrated with cabal

http://www.haskell.org/haddock/

62

Preliminaries

A Quick Dip into Haskell

Fancy Types

Rich Libraries

Practical Tools

HACKAGE

The aforementioned online repository of cabal packages along


with their associated haddock documentation.

Packages and their documentation are indexed and


searchable via a web interface
Package authors can upload directly from cabal after
registering
Users can download directly with cabal as well

http://www.haskell.org/haddock/

63

Preliminaries

A Quick Dip into Haskell

Fancy Types

Rich Libraries

Practical Tools

CRITEREON

Benchmarking done right.

Helps you ensure you are measuring the evaluation that you
want to be measuring
Performs statistical analysis of results to help determine the
reliability of the numbers
Produces pretty HTML results, including graphs

http://hackage.haskell.org/package/criterion

64

Preliminaries

A Quick Dip into Haskell

Fancy Types

Rich Libraries

Practical Tools

TASTY

A framework (a nice example from several available) for


composing various test libraries into a test suite.

Supports most of the lower-level test libraries available on


hackage
Integrates unit testing, property testing, etc.
Can output human and computer readable results
Tests to run can be filtered
Supports plugins for more advanced usage

https://hackage.haskell.org/package/tasty

65

Preliminaries

A Quick Dip into Haskell

Fancy Types

Rich Libraries

Practical Tools

QUICKCHECK / SMALLCHECK

Auto-derived fuzz testing based on type signatures

Describe some invariants for your algorithms and these will


try to find counterexamples
Test values are generated randomly for quickcheck,
exhaustively for smallcheck
Just provide Arbitrary instances for your types

https://hackage.haskell.org/package/quicktest
https://hackage.haskell.org/package/smallcheck

66

Das könnte Ihnen auch gefallen