Presentation is loading. Please wait.

Presentation is loading. Please wait.

© M. Winter COSC 4P41 – Functional Programming 9.19.1 Programming with actions Why is I/O an issue? I/O is a kind of side-effect. Example: Suppose there.

Similar presentations


Presentation on theme: "© M. Winter COSC 4P41 – Functional Programming 9.19.1 Programming with actions Why is I/O an issue? I/O is a kind of side-effect. Example: Suppose there."— Presentation transcript:

1 © M. Winter COSC 4P41 – Functional Programming 9.19.1 Programming with actions Why is I/O an issue? I/O is a kind of side-effect. Example: Suppose there is an operation inputInt :: Int-- reads an integer inputDiff = inputInt – inputInt inputInt 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.

2 © M. Winter COSC 4P41 – Functional Programming 9.29.2 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).

3 © M. Winter COSC 4P41 – Functional Programming 9.39.3 Reading input and writing output getLine :: IO String getChar :: IO Char putStr :: String -> IO () print :: Show a => a -> IO () where () is the type containing exactly one element; the element (). Remark: In WinGHCi just those I/O actions of type IO () are actually printed to the screen.

4 © M. Winter COSC 4P41 – Functional Programming 9.49.4 The do notation 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.

5 © M. Winter COSC 4P41 – Functional Programming 9.59.5 Examples putStrLn :: String -> IO () putStrLn str = do putStr str putStr ”\n” read2lines :: IO () read2lines = do getLine getLine puStrLn ”Two lines read.” getNput :: IO () getNput = do line <- getLine putStrLn line where line names the result of getLine (local variable).

6 © M. Winter COSC 4P41 – Functional Programming 9.69.6 Examples (cont’d) reverse2lines :: IO () reverse2lines = do line1 <- getLine line2 <- getLine let rev1 = reverse line1 let rev2 = reverse line2 putStrLn rev1 putStrLn rev2 getInt :: IO Int getInt = do line <- getLine return (read line :: Int) where return :: a -> IO a packs an a value in the IO monad.

7 © M. Winter COSC 4P41 – Functional Programming 9.79.7 Examples (cont’d) Notice, that the following program is not type correct: getInt = do line <- getLine (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 () -> IO () while test action = do res <- test if res then do action while test action else return ()

8 © M. Winter COSC 4P41 – Functional Programming 9.89.8 Examples (cont’d) isEOF :: IO Bool copyInputToOutput :: IO () copyInputToOutput = while (do res <- isEOF return (not res)) (do line <- getLine putStrLn line)

9 © M. Winter COSC 4P41 – Functional Programming 9.99.9 Examples (cont’d) goUntilEmpty :: IO () goUntilEmpty = do line <- getLine if line == [] then return () else (do putStrLn line goUntilEmpty) goUntilEmpty’ :: IO () goUntilEmpty’ = do line <- getLine while (return (line /= [])) (do putStrLn line line <- getLine return ()) does not work since variables cannot be updated. here we create a new variable

10 © M. Winter COSC 4P41 – Functional Programming 9. 10 Calculator example data Expr = Lit Int | Var Var | Op Ops Expr 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 commLine :: String -> Command eval :: Expr -> Store -> Int

11 © M. Winter COSC 4P41 – Functional Programming 9. 11 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, newSt) where val = eval e st newSt = update st v val calcStep :: Store -> IO Store calcStep st = doline <- getLine comm <- return (commLine line) (val, newSt) <- return (command comm st) print val return newSt

12 © M. Winter COSC 4P41 – Functional Programming 9. 12 Calculator example (cont’d) calcSteps :: Store -> IO () calcSteps st = while notEOF (do newSt <- calcStep st calcSteps newSt) notEOF :: IO Bool notEOF = do res <- isEOF return (not res) mainCalc :: IO () mainCalc = calcSteps initial

13 © M. Winter COSC 4P41 – Functional Programming 9. 13 Further I/O File I/O –readFile :: FilePath -> IO String –writeFile :: FilePath -> String -> IO () –appendFile :: FilePath -> String -> IO () Errors –ioError :: 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.

14 © M. Winter COSC 4P41 – Functional Programming 9. 14 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 <- getLine putStrLn 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

15 © M. Winter COSC 4P41 – Functional Programming 9. 15 Monads (cont’d) class Monad m where (>>=) :: m a -> (a -> m b) -> m b return :: a -> m a (>>) :: m a -> m b -> 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.

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

17 © M. Winter COSC 4P41 – Functional Programming 9. 17 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 <- getLine putStrLn line putStrLn ”That’s it.” return 5 is translated to getLine >>= putStrLn >> putStrLn ”That’s it.” >> return 5

18 © M. Winter COSC 4P41 – Functional Programming 9. 18 Examples of monads Identity monad –m a = a –m >>= f = 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 = k x Nothing >>= k = Nothing return = Just fail s = Nothing

19 © M. Winter COSC 4P41 – Functional Programming 9. 19 Examples of monads (cont’d) Parsing monad (Parsec – a useful parser combinator library) –Import statement: import Text.ParserCombinators.Parsec The type GenParser 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. GenParser combines 3 monadic structures (parser monad, state monad, error monad) into one data structure.

20 © M. Winter COSC 4P41 – Functional Programming 9. 20 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) (Tree a) Moon Dweezil Ahmet Moon 0 2 1 1 0 

21 © M. Winter COSC 4P41 – Functional Programming 9. 21 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 (newTab,y) = st tab (State trans) = f y in trans newTab)

22 © M. Winter COSC 4P41 – Functional Programming 9. 22 Examples of monads (cont’d) numberTree :: Eq a => Tree a -> State a (Tree Int) numberTree Nil = return Nil numberTree (Node x t1 t2) = do num <- numberNode x nt1 <- numberTree t1 nt2 <- numberTree t2 return (Node num nt1 nt2) numberNode :: Eq a => a -> State a Int numberNode x = State (nNode x) nNode :: Eq a => a -> (Table a -> (Table a, Int)) nNode x table | elem x table = (table, lookup x table) | otherwise = (table++[x], length table)

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

24 © M. Winter COSC 4P41 – Functional Programming 9. 24 Some Monad Functions Module Prelude readFile :: FilePath -> IO String sequence :: Monad m => [m a] -> m [a] sequence_ :: Monad m => [m a] -> m () mapM :: Monad m => (a -> m b) -> [a] -> m [b] mapM_ :: Monad m => (a -> m b) -> [a] -> m () Module Data.IORef (updatable varibles, i.e., a state monad) newIORef :: a -> IO (IORef a) readIORef :: IORef a -> IO a writeIORef :: IORef a -> a -> IO ()


Download ppt "© M. Winter COSC 4P41 – Functional Programming 9.19.1 Programming with actions Why is I/O an issue? I/O is a kind of side-effect. Example: Suppose there."

Similar presentations


Ads by Google