COSC 4 P 41 Functional Programming with actions

  • Slides: 24
Download presentation
COSC 4 P 41 – Functional Programming with actions Why is I/O an issue?

COSC 4 P 41 – Functional Programming with actions Why is I/O an issue? • I/O is a kind of side-effect. Example: Suppose there is an operation input. Int : : Int -- reads an integer input. Diff = input. Int – input. Int • input. Int should return two different values (depending on the users input). Hence, its evaluation depends on the context where (or when) it is executed side-effect!!! The meaning of an expression relying on side-effects is no longer determined by looking only at the meanings of its parts. © M. Winter 9. 1

COSC 4 P 41 – Functional Programming Monadic I/O • • The Haskell type

COSC 4 P 41 – Functional Programming Monadic I/O • • The Haskell type IO a is the type of I/O actions of type a, e. g. , the elements of a are somehow wrapped into an I/O container; the monad IO. An expression of type IO a is a program which will do some I/O and then return a value of type a. One way of looking at the I/O a types is that they provide a simple imperative language for writing I/O programs on top of Haskell, without compromising the functional model of Haskell. This approach is called the monadic approach. It is more general and can be used to incorporate side-effect into a pure functional programming language (without its problems). © M. Winter 9. 2

COSC 4 P 41 – Functional Programming Reading input and writing output get. Line

COSC 4 P 41 – Functional Programming Reading input and writing output get. Line : : IO String get. Char : : IO Char put. Str : : String -> IO () print : : Show a => a -> IO () where () is the type containing exactly one element; the element (). Remark: In Win. GHCi just those I/O actions of type IO () are actually printed to the screen. © M. Winter 9. 3

COSC 4 P 41 – Functional Programming The do notation is a flexible mechanism.

COSC 4 P 41 – Functional Programming The do notation is a flexible mechanism. With respect to the monad IO it supports two things: • it is used to sequence I/O programs, and • it is used to ‘capture’ the values returned by IO actions and so to pass these values to actions which follow them in the program. In general: • it is used to sequence programs wrapped in monad, and • it is used to unwrap the values returned by the monad and so to pass these values to actions which follow them in the program. © M. Winter 9. 4

COSC 4 P 41 – Functional Programming Examples put. Str. Ln : : String

COSC 4 P 41 – Functional Programming Examples put. Str. Ln : : String -> IO () put. Str. Ln str = do put. Str str put. Str ”n” read 2 lines : : IO () read 2 lines = do get. Line pu. Str. Ln ”Two lines read. ” get. Nput : : IO () get. Nput = do line <- get. Line put. Str. Ln line where line names the result of get. Line (local variable). © M. Winter 9. 5

COSC 4 P 41 – Functional Programming Examples (cont’d) reverse 2 lines : :

COSC 4 P 41 – Functional Programming Examples (cont’d) reverse 2 lines : : IO () reverse 2 lines = do line 1 <line 2 <let rev 1 let rev 2 put. Str. Ln get. Line = reverse line 1 = reverse line 2 rev 1 rev 2 get. Int : : IO Int get. Int = do line <- get. Line return (read line : : Int) where return : : a -> IO a packs an a value in the IO monad. © M. Winter 9. 6

COSC 4 P 41 – Functional Programming Examples (cont’d) Notice, that the following program

COSC 4 P 41 – Functional Programming Examples (cont’d) Notice, that the following program is not type correct: get. Int = do line <- get. Line (read line : : Int) Each component of a do construction has to be an element of IO a for a type a. while : : IO Bool -> IO () while test action = do res <- test if res then do action while test action else return () © M. Winter 9. 7

COSC 4 P 41 – Functional Programming Examples (cont’d) is. EOF : : IO

COSC 4 P 41 – Functional Programming Examples (cont’d) is. EOF : : IO Bool copy. Input. To. Output : : IO () copy. Input. To. Output = while (do res <- is. EOF return (not res)) (do line <- get. Line put. Str. Ln line) © M. Winter 9. 8

COSC 4 P 41 – Functional Programming Examples (cont’d) go. Until. Empty : :

COSC 4 P 41 – Functional Programming Examples (cont’d) go. Until. Empty : : IO () go. Until. Empty = do line <- get. Line if line == [] then return () else (do put. Str. Ln line go. Until. Empty) does not work since variables go. Until. Empty’ : : IO () cannot be updated. go. Until. Empty’ = do line <- get. Line while (return (line /= [])) (do put. Str. Ln line here we create a new variable line <- get. Line return ()) © M. Winter 9. 9

COSC 4 P 41 – Functional Programming Calculator example data Expr = Lit Int

COSC 4 P 41 – Functional Programming Calculator example data Expr = Lit Int | Var | Op Ops Expr data Ops = Add | Sub | Mul | Div | Mod type Var = Char initial : : Store value : : Store -> Var -> Int update : : Store -> Var -> Int -> Store data Command = Eval Expr | Assign Var Expr | Null comm. Line : : String -> Command eval : : Expr -> Store -> Int © M. Winter 9. 10

COSC 4 P 41 – Functional Programming Calculator example (cont’d) command : : Command

COSC 4 P 41 – Functional Programming Calculator example (cont’d) command : : Command -> Store -> (Int, Store) command Null st = (0 , st) command (Eval e) st = (eval e st , st) command (Assign v e) st = (val , new. St) where val = eval e st new. St = update st v val calc. Step : : Store -> IO Store calc. Step st = do line <- get. Line comm <- return (comm. Line line) (val , new. St) <- return (command comm st) print val return new. St © M. Winter 9. 11

COSC 4 P 41 – Functional Programming Calculator example (cont’d) calc. Steps : :

COSC 4 P 41 – Functional Programming Calculator example (cont’d) calc. Steps : : Store -> IO () calc. Steps st = while not. EOF (do new. St <- calc. Step st calc. Steps new. St) not. EOF : : IO Bool not. EOF = do res <- is. EOF return (not res) main. Calc : : IO () main. Calc = calc. Steps initial © M. Winter 9. 12

COSC 4 P 41 – Functional Programming Further I/O • File I/O – read.

COSC 4 P 41 – Functional Programming Further I/O • File I/O – read. File : : File. Path -> IO String – write. File : : File. Path -> String -> IO () – append. File : : File. Path -> String -> IO () • Errors – io. Error : : IOError -> IO a – catch : : IO a -> (IOError -> IO a) -> IO a where IOError is the system-dependent data type of I/O errors. More on error handling (especially the type IOError) can be found in the documentation for the I/O library IO. hs. © M. Winter 9. 13

COSC 4 P 41 – Functional Programming Monads IO is a type constructor, i.

COSC 4 P 41 – Functional Programming Monads IO is a type constructor, i. e. , an operation on types. It maps a type a to the type IO a of I/O action on a. A characteristic of the I/O monad is that it allows to sequence operations. do line <- get. Line put. Str. Ln line What is the type of such a combinator which sequences the operations: (>>=) : : IO a -> (a -> IO b) -> IO b or, more general, for an arbitrary type constructor m, a combinator (>>=) : : m a -> (a -> m b) -> m b © M. Winter 9. 14

COSC 4 P 41 – Functional Programming Monads (cont’d) class Monad m where (>>=)

COSC 4 P 41 – Functional Programming Monads (cont’d) class Monad m where (>>=) : : m a -> (a -> m b) -> m b return : : a -> m a (>>) : : m a -> m b fail : : String -> m a m >> k = m >>= _ -> k fail s = error s Requirements (informally): • The operation return x should simply return the value x, without any additional computational effect. • The sequencing given by >>= should be irrelevant of the way that expressions are bracketed. • >> acts like >>=, except that the value returned by the first expression is discarded rather than being passed to the second argument. • The value fail s corresponds to a computation that fails, giving the error message s. © M. Winter 9. 15

COSC 4 P 41 – Functional Programming Rules for monads (>@>) : : Monad

COSC 4 P 41 – Functional Programming Rules for monads (>@>) : : Monad m => (a -> m b) -> (b -> m c) -> (a -> mc) f >@> g = x -> (f x) >>= g Rules that should be satisfied: (M 1) return >@> f = f identity law (left) (M 2) f >@> return = f identity law (right) (M 3) (f >@> g) >@> h = f >@> (g >@> h) associativity In terms of (>>=): (M 1) (return x) >>= f (M 2) m >>= return (M 3) (m >>= f) >>= g = f x = m >>= (x -> (f x) >>= g) In category theory (>@>) is called the Kleisli composition. © M. Winter 9. 16

COSC 4 P 41 – Functional Programming The do notation revisited The do notation

COSC 4 P 41 – Functional Programming The do notation revisited The do notation can be used for arbitrary monads (not just for the I/O monad). It just a shorthand for an expression build up from (>>=) and (>>). Example: do line <- get. Line put. Str. Ln line put. Str. Ln ”That’s it. ” return 5 is translated to get. Line >>= put. Str. Ln >> put. Str. Ln ”That’s it. ” >> return 5 © M. Winter 9. 17

COSC 4 P 41 – Functional Programming Examples of monads • • Identity monad

COSC 4 P 41 – Functional Programming Examples of monads • • Identity monad – m a = a – m >>= f m – return = id I/O monad List monad instance Monad [] where xs >>= f = concat (map f xs) return x = [x] fail s = [] Maybe monad (Error monad) instance Monad Maybe where (Just x) >>= k x Nothing >>= k = Nothing return = Just fail s = Nothing © M. Winter 9. 18

COSC 4 P 41 – Functional Programming Examples of monads (cont’d) • Parsing monad

COSC 4 P 41 – Functional Programming Examples of monads (cont’d) • Parsing monad (Parsec – a useful parser combinator library) – Import statement: import Text. Parser. Combinators. Parsec The type Gen. Parser a state b • is the type of parsers taking lists of a elements as input producing an element of b. • is implemented similar to the type Parser from Week 7. • has a parameter state. This parameter can be used as an internal state storing information during the parsing process. • has an internal and hidden error state. This state is used to keep track of errors that occurred during the parsing process. Gen. Parser combines 3 monadic structures (parser monad, state monad, error monad) into one data structure. © M. Winter 9. 19

COSC 4 P 41 – Functional Programming Examples of monads (cont’d) • State monad

COSC 4 P 41 – Functional Programming Examples of monads (cont’d) • State monad – a state monad is a type of the form State a b = a -> (a, b) where the type constructor is State a. – An operation of this type can change the state (of type a) before returning a value of type b. – Example: data Tree a = Nil | Node a (Tree a) Moon Ahmet 0 Dweezil Ahmet © M. Winter Moon 1 2 1 0 9. 20

COSC 4 P 41 – Functional Programming Examples of monads (cont’d) type Table a

COSC 4 P 41 – Functional Programming Examples of monads (cont’d) type Table a = [a] data State a b = State (Table a -> (Table a , b)) instance Monad (State a) where return x = State (tab -> (tab, x)) (State st) >>= f = State (tab -> let (new. Tab, y) = st tab (State trans) = f y in trans new. Tab) © M. Winter 9. 21

COSC 4 P 41 – Functional Programming Examples of monads (cont’d) number. Tree :

COSC 4 P 41 – Functional Programming Examples of monads (cont’d) number. Tree : : Eq a => Tree a -> State number. Tree Nil = return Nil number. Tree (Node x t 1 t 2) = do num <nt 1 <nt 2 <return a (Tree Int) number. Node x number. Tree t 1 number. Tree t 2 (Node num nt 1 nt 2) number. Node : : Eq a => a -> State a Int number. Node x = State (n. Node x) n. Node : : Eq a => a -> (Table a , Int)) n. Node x table | elem x table = (table , lookup x table) | otherwise = (table++[x] , length table) © M. Winter 9. 22

COSC 4 P 41 – Functional Programming Examples of monads (cont’d) extract : :

COSC 4 P 41 – Functional Programming Examples of monads (cont’d) extract : : State a b -> b extract (State st) = snd (st []) num. Tree : : Eq a => Tree Int num. Tree = extract. number. Tree © M. Winter 9. 23

COSC 4 P 41 – Functional Programming Some Monad Functions Module Prelude • •

COSC 4 P 41 – Functional Programming Some Monad Functions Module Prelude • • • read. File : : File. Path -> IO String sequence : : Monad m => [m a] -> m [a] sequence_ : : Monad m => [m a] -> m () map. M : : Monad m => (a -> m b) -> [a] -> m [b] map. M_ : : Monad m => (a -> m b) -> [a] -> m () Module Data. IORef (updatable varibles, i. e. , a state monad) • new. IORef : : a -> IO (IORef a) • read. IORef : : IORef a -> IO a • write. IORef : : IORef a -> IO () © M. Winter 9. 24