1 Haskell Kevin Atkinson John Simmons. 2 Contents Introduction Type System Variables Functions...

of 25 /25
1 Haskell Kevin Atkinson John Simmons

Transcript of 1 Haskell Kevin Atkinson John Simmons. 2 Contents Introduction Type System Variables Functions...

1

Haskell

Kevin Atkinson

John Simmons

2

Contents

• Introduction

• Type System

• Variables

• Functions

• Module System

• I/O

• Conclusions

3

History of Haskell

• Named for Haskell Curry

• Created by committee from FPCA conference, 1987– Needed a “standard” non-strict, purely

functional language

• Latest version: Haskell 98

4

Goals of the Haskell design

• Suitability for teaching, research, and applications

• Complete description via the publication of a formal syntax and semantics

• Free availability• Basis of ideas that enjoy a wide consensus• Reduction of unnecessary diversity in

functional programming languages

5

Interpreters and Compilers

• GHC

• nhc98

• HBC / HBI

• Hugs

• www.haskell.org/implementations.html

6

Distinguishing features

• Lazy evaluation

• Stateless

• No exception system - errors are considered equivalent to _|_

7

Variants and extensions

• Parallel variants

• Object support

• Pattern guards

• Views

8

The Haskell type system

• value :: Type

• Type inference

• Pre-defined types– Integer, Real, String, etc. <= case sensitive!– Not special

• Polymorphic types

• User-defined types

9

User-defined types

• Keywords type and data• Enumerated types, renamed types, tuples

(record types), lists• Type classes

– ex. Equality types– Inheritance ex. Equality => Ordered

• Kinds of types - verify type constructors– * means a value type

10

Thunks and !

• Lazy evaluation: the computation needed to compute a field value is stored until needed in a thunk

• ! Will force immediate evaluation– Can help constrain types– Use with caution

11

Variables

• No keywords to define

• Lists (constructor is : )

• Arrays– must open the Array module

• Infinite data structures

12

Basic Stuff

• Due to layout rules Haskell syntax is rather elegant and generally easy to understand

• Functions similar to ML• Pattern and Wildcards like ML

– but also more powerful Pattern Gards

– Case clause to pattern match inside of functions

• Let like ML to define bindings– but also where as part of function and case clause

syntax to declare binding after the expression

13

More on Lists• [ f x | x <- xs, x < 10 ]

– Reads "the list of all f x such that x is drawn from xs where x < 10"

– x <- xs is a generator, x < 10 is a guard

• More than one generator can be specifed:[ (x,y) | x <- xs, y <- ys ]

– Which forms the cartesian product of the two lists xs and ys• [1 .. 10] => [1,2,3,4,5,6,7,8,9,10]• [1,3 .. 10] => [1, 3, 5, 7, 9]• ints = [1, 2 ..]

– take 10 ints => [1,2,3,4,5,6,7,8,9,10]– squares = map (^2) ints– take 3 squares => [1, 3, 9]

• numsFrom n = n : numsFrom (n+1)• ones = 1 : ones

Fibonacci

• fib = 1 : 1 : [ a+b | (a,b) <- zip fib (tail fib) ]– Where zip returns the pairwise interleaving of its two list arguments:

zip (x:xs) (y:ys) = (x,y) : zip xs yszip xs ys = []

– An infinite list, defined in terms of itself, as if it were "chasing its tail."

15

Lazy Evaluation• No Fixed Order of Evaluation• let f x y = a

where a = 20 * b b = x + 5 * c c = y * y

• As you already see infinite lists are not possible

• Proving program correctness is nothing more than a mathematical proof. Not so in ML because one still has to worry about order of evaluation

• Many things that were inefficient with strict evaluation or now possible in Haskell.

– Can perform complicated operations by function composition.

• And Finally … No side effects or State.

16

Standard Prelude

• . $ $! flip curry/uncurry id const until • head/tail ++ length concat reverse • zip zipWith• map fold* filter • take/drop iterate repeat cycle span• any/all elem sum/product maximum/minimum• lines words

17

Using The Standard Prelude• wordCount = length . words• fact n = product (take n [1, 2 ..])• infixl 9 .|

(.|) = flip (.)• doubleSpace = lines .| map (++ “\n\n”)

.| concat• summary = words .| take 20 .| unwords• wordlist = words

.| filter (\x -> length x > 3) .| map (to lower) .| group .| filter (\x length x >= 3) .| map head .| map (++ “\n”) .| concat

18

Error Conditions• Often handled using the Maybe type defined in the

Standard Prelude– data Maybe a = Just a | Nothing

• doQuery :: Query -> DB -> Maybe Record• r :: Maybe Record

r = case doQuery db q1 of Nothing -> Nothing Just r1 -> case do Query db (q2 r1) of Nothing -> Nothing Just r2 -> case doQuery db (q3 r2) of Nothing -> Nothing

Just r3 -> ...• Which can get quite tedious after a while• There has to be a better way…

19

• And there is...• thenMB :: Maybe a -> (a -> Maybe b) -> Maybe b

mB `thenMB` f = case mB of Nothing -> Nothing

Just a -> f areturnMB a = Just a

• r = doQuery q1 db `thenMB` \r1 -> doQuery (q2 r1) db `thenMB` \r2 -> doQuery (q3 r2) db `thenMB` \r3 -> returnMB r3

• And what we have is the mathematical notion of Monad which is formally defined as:

return a `then` f === f a m `then` return === mm `then` (\a -> f a `then` h) === (m `then` f) `then` h

Monads

20

Haskell Monads• In Haskell a Monad is a class defined something like:• class Monad m where

>>= :: m a -> (a -> m b) -> m b return :: a -> m a

• So for our Database example we will have something like• instance Monad Maybe where

(>>=) = thenMB return = returnMB

• doQuery q1 db >>= \r1 -> doQuery (q2 r1) db >>= \r2 ->doQuery (q3 r2) db >>= \r3 ->return r3

• Which can be rewritten using Haskell’s do syntax• do r1 <- doQuery q1 db

r2 <- doQuery q2 db r3 <- doQuery q3 db return r3

21

Simulating State

• To simulate state when there is none simply pass in the state and return a copy of the new state.

• parm -> SomeState -> (res, SomeState)

• Functions that do so are known as State Transformers.

• We can model this notation in Haskell using a type synonym

• type StateT s a = s -> (a, s)• parm -> StateT SomeState res

22

State Example• addRec :: Record -> DB -> (Bool,DB)• addRec :: Record -> StateT DB Bool• newDB :: StateT DB Bool

newDB db = let (bool1,db1) = addRec rec1 db (bool2,db2) = addRec rec2 db1 (bool3,db3) = delRec rec3 db2

in (bool1 && bool2 && bool3)

• As you can see this could get quite tedious

• However, with Monads we can abstract the state passing details away. The details or a bit complicated, but the end result will look something like this:

• do boo11 <- addRec rec1 bool2 <- addRec rec2 bool3 <- addRec rec3 return (bool1 && bool2 && bool3)

23

I / O• To Perform I/O A State Transformer Must be used, for

example to get a character:getChar :: FileHandle -> StateT World Char

• But we must make sure each World is only passed to one function so a Monad is used

• But this is open to abuse so an ADT must be used:data IO a = IO (StateT World a)

• So putChar is now:getChar :: FileHandle -> IO Char

• The end result is that any function which uses I/O must return the IO type.

• And the only way IO can be executed is by declaring the function “main :: IO ()”.

24

Finally A Complete Program• import System (getArgs)

main :: IO ()main = do args <- getArgs case args of[fname] -> do fstr <- readFile fname

let nWords = length . words $ fstr nLines = length . lines $ fstr

nChars = length fstr putStrLn . unwords $ [ show nLines

, show nWords , show nChars , fname]

_ -> putStrLn "usage: wc fname"

25

• Hudak, P. et al (2000) “A Gentle Introduction to Haskell Version 98” http://www.haskell.org/tutorial

• Jones, S.P. et al (1999) “The Haskell 98 Report” http://www.haskell.org/onlinereport

• Winstanley, Noel (1999) “What the Hell are Monads?” http://www.dcs.gla.ac.uk/~nww/Monad.html

References