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

Upload
pollyhensley 
Category
Documents

view
228 
download
5
Transcript of 1 Haskell Kevin Atkinson John Simmons. 2 Contents Introduction Type System Variables Functions...
3
History of Haskell
• Named for Haskell Curry
• Created by committee from FPCA conference, 1987– Needed a “standard” nonstrict, 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 __
8
The Haskell type system
• value :: Type
• Type inference
• Predefined types– Integer, Real, String, etc. <= case sensitive!– Not special
• Polymorphic types
• Userdefined types
9
Userdefined 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"