eecs 700 functional programming - ittc.ku.eduandygill/teaching/2010/eecs700/slides12.pdf ·...

27
EECS 700 Functional Programming Dr. Andy Gill University of Kansas April 1, 2010 1 / 27

Upload: others

Post on 07-Jul-2020

4 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: EECS 700 Functional Programming - ittc.ku.eduandygill/teaching/2010/EECS700/slides12.pdf · Functional Programming Dr. Andy Gill University of Kansas April 1, 2010 1/27. IO and Haskell

EECS 700Functional Programming

Dr. Andy Gill

University of Kansas

April 1, 2010

1 / 27

Page 2: EECS 700 Functional Programming - ittc.ku.eduandygill/teaching/2010/EECS700/slides12.pdf · Functional Programming Dr. Andy Gill University of Kansas April 1, 2010 1/27. IO and Haskell

IO and Haskell

Only things that return an IO

can do IO.

2 / 27

Page 3: EECS 700 Functional Programming - ittc.ku.eduandygill/teaching/2010/EECS700/slides12.pdf · Functional Programming Dr. Andy Gill University of Kansas April 1, 2010 1/27. IO and Haskell

IO and Polymorphism

A polymorphic argument can returnanything , so can be used to constructan IO, but only if someone else providesthe construction of the polymorphicargument.

3 / 27

Page 4: EECS 700 Functional Programming - ittc.ku.eduandygill/teaching/2010/EECS700/slides12.pdf · Functional Programming Dr. Andy Gill University of Kansas April 1, 2010 1/27. IO and Haskell

> :t foldr(a -> b -> b) -> b -> [a] -> blet put str more = putStrLn str >> more*Main> :t putput :: String -> IO b -> IO b> :t foldr put (return ()) (words "Hello World")IO ()> foldr put (return ()) (words "Hello World")HelloWorld>

foldr helped build the IO command,but did not actually execute the IO actions directly.

4 / 27

Page 5: EECS 700 Functional Programming - ittc.ku.eduandygill/teaching/2010/EECS700/slides12.pdf · Functional Programming Dr. Andy Gill University of Kansas April 1, 2010 1/27. IO and Haskell

> :t [ putStrLn (show n) | n <- [1..10]][ putStrLn (show n) | n <- [1..10]] :: [IO ()]> [ putStrLn (show n) | n <- [1..10]]<interactive>:1:0:

No instance for (Show (IO ()))arising from a use of ‘print’ at <interactive>:1:0-34

Possible fix: add an instance declaration for (Show (IO ()))In a stmt of a ’do’ expression: print it

>:t sequencesequence :: (Monad m) => [m a] -> m [a]> sequence [ putStrLn (show n) | n <- [1..10]]123...10[(),(),(),(),(),(),(),(),(),()]> :t sequence_sequence_ :: (Monad m) => [m a] -> m ()

5 / 27

Page 6: EECS 700 Functional Programming - ittc.ku.eduandygill/teaching/2010/EECS700/slides12.pdf · Functional Programming Dr. Andy Gill University of Kansas April 1, 2010 1/27. IO and Haskell

File IO in Haskell

import Data.Char

main = dostr <- readFile "Example.hs"let str’ = map toUpper strwriteFile "outfile" str’

IMPORT DATA.CHAR

MAIN = DO

STR <- READFILE "EXAMPLE.HS"

LET STR’ = MAP TOUPPER STR

WRITEFILE "OUTFILE" STR’

6 / 27

Page 7: EECS 700 Functional Programming - ittc.ku.eduandygill/teaching/2010/EECS700/slides12.pdf · Functional Programming Dr. Andy Gill University of Kansas April 1, 2010 1/27. IO and Haskell

import Data.Charimport System.IO

main = doin_h <- openFile "Example2.hs" ReadModeout_h <- openFile "outfile2" WriteModeloop $ do str <- hGetLine in_h

hPutStrLn out_h (map toUpper str)

loop m = m >> loop m

$ ./Example2Example2: Example.hs: hGetLine: end of file

7 / 27

Page 8: EECS 700 Functional Programming - ittc.ku.eduandygill/teaching/2010/EECS700/slides12.pdf · Functional Programming Dr. Andy Gill University of Kansas April 1, 2010 1/27. IO and Haskell

import Data.Charimport System.IO

main = doin_h <- openFile "Example2.hs" ReadModeout_h <- openFile "outfile2" WriteModelet loop = do

eof <- hIsEOF in_hif eofthen return ()else do str <- hGetLine in_h

hPutStrLn out_h (map toUpper str)loop

loophClose in_hhClose out_h

8 / 27

Page 9: EECS 700 Functional Programming - ittc.ku.eduandygill/teaching/2010/EECS700/slides12.pdf · Functional Programming Dr. Andy Gill University of Kansas April 1, 2010 1/27. IO and Haskell

IO Style Exceptions in Haskell

-- inside System.IO.Error

catch :: IO a -> (IOError -> IO a) -> IO a

ioError :: IOError -> IO a

isEOFError :: IOError -> Bool...

9 / 27

Page 10: EECS 700 Functional Programming - ittc.ku.eduandygill/teaching/2010/EECS700/slides12.pdf · Functional Programming Dr. Andy Gill University of Kansas April 1, 2010 1/27. IO and Haskell

Asynchronous Exceptions in Haskell

-- inside Control.Exception (in ghc 6.10)

catch :: Exception e => IO a -> (e -> IO a) -> IO a

throw :: Exception e => e -> a -- no IO monad!throwIO :: Exception e => e -> IO a...

10 / 27

Page 11: EECS 700 Functional Programming - ittc.ku.eduandygill/teaching/2010/EECS700/slides12.pdf · Functional Programming Dr. Andy Gill University of Kansas April 1, 2010 1/27. IO and Haskell

Asynchronous Exceptions in Haskell (continued)

import Control.Exception as E

main = do(if 99 ‘div‘ 0 == 4

then print "Hello"else print "World")

‘E.catch‘ (\ e -> print $ "Caught Problem: "++ show (e :: SomeException))

> main"Caught Problem: divide by zero">

11 / 27

Page 12: EECS 700 Functional Programming - ittc.ku.eduandygill/teaching/2010/EECS700/slides12.pdf · Functional Programming Dr. Andy Gill University of Kansas April 1, 2010 1/27. IO and Haskell

Laziness and Asynchronous Exceptions

import Control.Exception as E

example = do(return (99 ‘div‘ 0 == 4))

‘E.catch‘ (\ e -> do print $ "Caught Problem: "++ show (e :: SomeException)

return False)

> example*** Exception: divide by zero>

12 / 27

Page 13: EECS 700 Functional Programming - ittc.ku.eduandygill/teaching/2010/EECS700/slides12.pdf · Functional Programming Dr. Andy Gill University of Kansas April 1, 2010 1/27. IO and Haskell

Laziness and Asynchronous Exceptions

import Control.Exception as E

example = do(return (99 ‘div‘ 0 == 4) >>= \ v -> evaluate v)

‘E.catch‘ (\ e -> do print $ "Caught Problem: "++ show (e :: SomeException)

return False)

> example"Caught Problem: divide by zero">

13 / 27

Page 14: EECS 700 Functional Programming - ittc.ku.eduandygill/teaching/2010/EECS700/slides12.pdf · Functional Programming Dr. Andy Gill University of Kansas April 1, 2010 1/27. IO and Haskell

Strange Function

-- inside Control.Exception (in ghc 6.10)

throwTo :: Exception e => ThreadId -> e -> IO ()

What does this mean? Can Haskell have many IO threads running?

14 / 27

Page 15: EECS 700 Functional Programming - ittc.ku.eduandygill/teaching/2010/EECS700/slides12.pdf · Functional Programming Dr. Andy Gill University of Kansas April 1, 2010 1/27. IO and Haskell

Forking Threads

-- inside Control.Concurrent

forkIO :: IO () -> IO ThreadId

-- alsothreadDelay :: Int -> IO ()killThread :: ThreadId -> IO ()throwTo :: Exception e => ThreadId -> e -> IO ()

15 / 27

Page 16: EECS 700 Functional Programming - ittc.ku.eduandygill/teaching/2010/EECS700/slides12.pdf · Functional Programming Dr. Andy Gill University of Kansas April 1, 2010 1/27. IO and Haskell

Channels Between Threads

-- inside Control.Concurrent.Chan

data Chan anewChan :: IO (Chan a)writeChan :: Chan a -> a -> IO ()readChan :: Chan a -> IO a -- can block

16 / 27

Page 17: EECS 700 Functional Programming - ittc.ku.eduandygill/teaching/2010/EECS700/slides12.pdf · Functional Programming Dr. Andy Gill University of Kansas April 1, 2010 1/27. IO and Haskell

IO and Haskell

Only things that return an IO

can do IO, have external effects, talk tothe network, do stuff.

Therefore, in the IO monad, you can doanything an imperative language can do.

17 / 27

Page 18: EECS 700 Functional Programming - ittc.ku.eduandygill/teaching/2010/EECS700/slides12.pdf · Functional Programming Dr. Andy Gill University of Kansas April 1, 2010 1/27. IO and Haskell

IO References (variables)

-- inside Data.IORefdata IORef a = ...

-- createnewIORef :: a -> IO (IORef a)

-- readreadIORef :: IORef a -> IO a

-- writewriteIORef :: IORef a -> a -> IO ()

18 / 27

Page 19: EECS 700 Functional Programming - ittc.ku.eduandygill/teaching/2010/EECS700/slides12.pdf · Functional Programming Dr. Andy Gill University of Kansas April 1, 2010 1/27. IO and Haskell

Forking Threads

-- inside Control.Concurrent

forkIO :: IO () -> IO ThreadId

-- alsothreadDelay :: Int -> IO ()killThread :: ThreadId -> IO ()throwTo :: Exception e => ThreadId -> e -> IO ()

19 / 27

Page 20: EECS 700 Functional Programming - ittc.ku.eduandygill/teaching/2010/EECS700/slides12.pdf · Functional Programming Dr. Andy Gill University of Kansas April 1, 2010 1/27. IO and Haskell

MVars: Mutable Concurrency Variables

-- inside Control.Concurrent.MVar

data MVar a = ...

-- creationnewMVar :: a -> IO (MVar a)newEmptyMVar :: IO (MVar a)

-- writing, can blockputMVar :: MVar a -> a -> IO ()

-- reading, can blocktakeMVar :: MVar a -> IO a

-- checkingisEmptyMVar :: MVar a -> IO Bool

20 / 27

Page 21: EECS 700 Functional Programming - ittc.ku.eduandygill/teaching/2010/EECS700/slides12.pdf · Functional Programming Dr. Andy Gill University of Kansas April 1, 2010 1/27. IO and Haskell

Channels Between Threads

-- inside Control.Concurrent.Chan

data Chan a

-- creationnewChan :: IO (Chan a)

-- writingwriteChan :: Chan a -> a -> IO ()

-- reading, can blockreadChan :: Chan a -> IO a

21 / 27

Page 22: EECS 700 Functional Programming - ittc.ku.eduandygill/teaching/2010/EECS700/slides12.pdf · Functional Programming Dr. Andy Gill University of Kansas April 1, 2010 1/27. IO and Haskell

% telnet www.haskell.org 80Trying 128.36.229.215...Connected to bugs.haskell.org.Escape character is ’^]’.GET / HTTP/1.1Host: localhost

HTTP/1.1 200 OK

Date: Fri, 03 Apr 2009 16:46:29 GMT

Server: Apache/2.0.46 (Red Hat)

Accept-Ranges: bytes

X-Powered-By: PHP/4.3.2

Content-language: en

ETag: W/"haskellwiki:pcache:idhash:1-0!1!0!0!1!en!2--20090328210221"

Vary: Accept-Encoding,Cookie

Expires: -1

Cache-Control: private, must-revalidate, max-age=0

Last-modified: Sat, 28 Mar 2009 21:02:21 GMT

Connection: close

Transfer-Encoding: chunked

Content-Type: text/html; charset=utf-8

6660

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"

"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en" >

...

22 / 27

Page 23: EECS 700 Functional Programming - ittc.ku.eduandygill/teaching/2010/EECS700/slides12.pdf · Functional Programming Dr. Andy Gill University of Kansas April 1, 2010 1/27. IO and Haskell

Sockets

listenOn :: PortID -> IO Socketdata PortID= Service String| PortNumber PortNumber| UnixSocket String

accept :: Socket -> IO (Handle, HostName, PortNumber)type HostName = Stringnewtype PortNumber = PortNum Word16

23 / 27

Page 24: EECS 700 Functional Programming - ittc.ku.eduandygill/teaching/2010/EECS700/slides12.pdf · Functional Programming Dr. Andy Gill University of Kansas April 1, 2010 1/27. IO and Haskell

API for our Webserver

initServer:: Int -- The port number-> (Request -> IO Response) -- The functionality of the Sever-> IO Server -- A token for the Server

type Server = ()data Request = Request {reqMethod :: String,reqURI :: URI,reqHeaders :: [(String, String)],reqBody :: String

}data Response = Response {resCode :: Int,resHeaders :: [(String, String)],resBody :: String

}

24 / 27

Page 25: EECS 700 Functional Programming - ittc.ku.eduandygill/teaching/2010/EECS700/slides12.pdf · Functional Programming Dr. Andy Gill University of Kansas April 1, 2010 1/27. IO and Haskell

API for our Webserver

initServer :: Int -> (Request -> IO Response) -> IO ServerinitServerMain processBody portNo callOut = do

sock <- listenOn (PortNumber $ fromIntegral portNo)loopIO(do (h,_nm,_port) <- accept sock

forkIO $ do ln <- hGetLine hcase words ln of[mode,uri,"HTTP/1.1"] ->case parseURIReference uri ofJust uri’ -> readHeaders h mode uri’ []_ -> hClose h

_ -> hClose hreturn ()

) ‘finally‘ sClose sockwhere

loopIO m = do mloopIO m

...

25 / 27

Page 26: EECS 700 Functional Programming - ittc.ku.eduandygill/teaching/2010/EECS700/slides12.pdf · Functional Programming Dr. Andy Gill University of Kansas April 1, 2010 1/27. IO and Haskell

readHeaders h mode uri hds = doline <- hGetLine hcase span (/= ’:’) line of("\r","") -> sendRequest h mode uri hds(name,’:’:rest) ->

readHeaders h mode uri(hds ++ [(name,dropWhile Char.isSpace rest)])

_ -> hClose h -- strange format

26 / 27

Page 27: EECS 700 Functional Programming - ittc.ku.eduandygill/teaching/2010/EECS700/slides12.pdf · Functional Programming Dr. Andy Gill University of Kansas April 1, 2010 1/27. IO and Haskell

sendRequest h mode uri hds = doresp <- callOut $ Request { reqMethod = mode

, reqURI = uri, reqHeaders = hds, reqBody = ""}

let body = resBody resphPutStr h $ concatMap (++"\r\n") $

("HTTP/1.1 " ++ message (resCode resp)) :("Connection: close") :("Content-Length", show (length body)) :(map (\(hdr,val) -> hdr ++ ": " ++ val) $

resHeaders resp) ++"" :[]

hPutStr h bodyhClose h

27 / 27