
Programming Languages Andrea Flexeder Chair for Theoretical Computer Science Prof. Seidl TU Munchen¨ winter term 2010/2011 Lecture 10 Side-Effects Main Points you should get: • Why monads? • What is a monad? • How to use a monad? C]: Lazy evaluation and side-effects static bool LessThanThirty(int x) { Console.Write("<0>? Less than 30;",x); return x < 30; } static bool MoreThanTwenty(int x) { Console.Write("<0>? More than 20;",x); return x > 20; } var q0 = from x in new[]<1,25,40,5,23> where LessThanThirty(x) select x; var q1 = from x in q0 where MoreThanTwenty(x) select x; foreach (var r in q1) Console.WriteLine("[<0>];",r); C]: Lazy evaluation and side-effects Output: • 1? Less than 30; • 1? More than 20; • 25? Less than 30; • 25? More than 20; • 40? Less than 30; • 5? Less than 30; • ::: Haskell lessThanThirty x = do {putStrLn ((show x) ++ " less than 30?"); return (x < 30) } moreThanTwenty x = do {putStrLn ((show x) ++ " more than 20?"); return (x > 20) } q0 = [x | x <- [1, 25, 50, 5, 23], lessThanThirty x] q1 = [x | x <- q0, moreThanTwenty x] Couldn’t match expected type ‘Bool’ against inferred type ‘IO Bool’ In the expression: moreThanTwenty 20 In a stmt of a list comprehension: moreThanTwenty 20 In the expression: [xjx q0, moreThanTwenty 20] Side-Effects Effect • besides producing a value, • modifying some state, • observable interaction with world/functions • e.g. global state, exception handling, I/O, non-determinism, . • ) control flow matters! Control Flow order in which actions/function calls are evaluated 2. monads aim: integrate impure side-effects into a pure functional language e.g. Haskell Discussion two ways of approaching effects in functional programming: 1. reference cells, sequence operator, functions with side-effect val x = ref 0 x := !x +1 print x e.g. Standard ML Discussion two ways of approaching effects in functional programming: 1. reference cells, sequence operator, functions with side-effect val x = ref 0 x := !x +1 print x e.g. Standard ML 2. monads aim: integrate impure side-effects into a pure functional language e.g. Haskell Monadic Style Characteristics: • make explicit sequence in which actions take place allows I/O operations in presence of laziness • usage of state dealing with global data objects crosscutting concerns: debugging, exception handling, etc. • concept from category theory • idea of E. Moggi (mathematical formalisation) • structuring denotational semantics • translated to functional programming by P. Wadler • alternative to CPS echoTwice :: IO () echoTwice = echo >> echo echoDup :: IO () echoDup = getChar >>= \c -> putChar c >> putChar c IO Example (1) echo :: IO () echo = getChar >>= putChar IO Example (1) echo :: IO () echo = getChar >>= putChar echoTwice :: IO () echoTwice = echo >> echo echoDup :: IO () echoDup = getChar >>= \c -> putChar c >> putChar c IO Example (2) getTwoChars :: IO (Char, Char) getTwoChars = getChar >>= \c1 -> getChar >>= \c2 -> ??????? IO Example (2) getTwoChars :: IO (Char, Char) getTwoChars = getChar >>= \c1 -> getChar >>= \c2 -> return (c1,c2) IO Monad • type constructor IO denotes computations interacting with operating system • return :: a ! IO a • (>>=) :: IO a ! (a ! IO b) ! IO b • interpretation of type IO a: computation with I/O and a return value of type a • return value of a computation should only be used in further computations and not as return value of a function! Basic Definition • type class Monad for monads with methods return and bind (>>=) • type constructor m • generation of a monad return :: Monad m => a ! m a • takes some value x • yields a monadic operation having only x as return value • composition of monadic computations (>>=) :: Monad m => m a ! (a ! m b) ! m b • 2nd computation uses return value of 1st computation • return value is return value of 2nd computation Monad Class type constructor class class Monad m :: (* ! *) where (>>=) :: forall a b . m a ! (a ! m b) ! m b (>>) :: forall a b . m a ! m b ! m b (return) :: forall a. a ! m a (fail) :: String ! m a m >> k = m >>= n ! k fail s = error s • each line in do-notation creates a new scope: • fun r = do x f r x g x x h x return x • fun r = f r >>= ((nx ! g x) >>= ((nx ! h x) >>= (nx ! return x))) Do Notation (Example) • fun a = return a >>= (nb ! (f b >>= (nc ! g b c) )) • in do-notation: fun b = do f c f b; g b c g equivalent to: fun b = do c f b g b c Do Notation (Example) • fun a = return a >>= (nb ! (f b >>= (nc ! g b c) )) • in do-notation: fun b = do f c f b; g b c g equivalent to: fun b = do c f b g b c • each line in do-notation creates a new scope: • fun r = do x f r x g x x h x return x • fun r = f r >>= ((nx ! g x) >>= ((nx ! h x) >>= (nx ! return x))) • equivalent to: do x1 e1; x2 e2; e3; x4 e4; e5 Do Notation • each e >>= nx ! ... becomes x e; ... • each e >> ... becomes e; ... • e1 >>= nx1 ! e2 >>= nx2 ! e3 >> e4 >>= nx4 ! e5 Do Notation • each e >>= nx ! ... becomes x e; ... • each e >> ... becomes e; ... • e1 >>= nx1 ! e2 >>= nx2 ! e3 >> e4 >>= nx4 ! e5 • equivalent to: do x1 e1; x2 e2; e3; x4 e4; e5 IO Example (2) in Do-Notation getTwoChars :: IO (Char, Char) getTwoChars = getChar >>= \c1 -> getChar >>= \c2 -> return (c1,c2) getTwoChars :: IO (Char,Char) getTwoChars = do { c1 <- getChar ; c2 <- getChar ; return (c1,c2) } IO in Haskell • entire Haskell program is wrapped inside the IO monad • main program is an action of type IO () • example: main :: IO () main = do putStr "Your name: " x <- getLine putStr ("Hello "++ x ++".\n") -- equivalent to main1 = putStr "Your name:" >>= \x -> getLine >>= \x -> putStr ("Hello "++ x ++".\n") • reconcile effects and referential transparency, laziness • disciplined way to encapsulate states (imperative style) (>>=) and return satisfy the laws of a monad: return v >>= nx ! m = m[x:=v] m >>= nx ! return x = m (m >>= nx ! n) >>= ny! o = m >>= nx ! (n >>= ny ! o) Monadic Laws guarantee that monadic composition is associative and has left and right unit 1. (return a) >>= f =) f a - - left unit 2. m >>= return =) m - - right unit 3. (m >>= f ) >>= g =) m >>= (nx ! f x >>= g) - - associativity Monadic Laws guarantee that monadic composition is associative and has left and right unit 1. (return a) >>= f =) f a - - left unit 2. m >>= return =) m - - right unit 3. (m >>= f ) >>= g =) m >>= (nx ! f x >>= g) - - associativity (>>=) and return satisfy the laws of a monad: return v >>= nx ! m = m[x:=v] m >>= nx ! return x = m (m >>= nx ! n) >>= ny! o = m >>= nx ! (n >>= ny ! o) • monoid examples: • (N0; +; 0) • (Z; +; 0) • (N; ∗; 1) • (Σ∗; concat; ) • (a; (++); [ ]) Monoid • algebraic structure (M; •; u): operator (•), value u, set M • operator has the value as identity u • x = x x • u = x • operator is associative ( x • y ) • z = x • (y • z) Monoid • algebraic structure (M; •; u): operator (•), value u, set M • operator has the value as identity u • x = x x • u = x • operator is associative ( x • y ) • z = x • (y • z) • monoid examples: • (N0; +; 0) • (Z; +; 0) • (N; ∗; 1) • (Σ∗; concat; ) • (a; (++); [ ]) Overview some instances of monads: • IO • Identity • Exception • State • Maybe • List Example: Interpreter Modularity and Extensibility: • Example: Interpreter • combination of interpreter and background information • enriched by following background info: 1. no: identity monad 2. errors: exception monad 3. operation counter: state monad Modification • environment contains computations instead of values type Env = [(Variable,M Value)] update :: Env ! Variable ! M Value ! Env • replacing each function of type a ! b by a function of type a ! M b • functions eval, add, myLookup have to be modified! Identity Monad module MonIdent where newtype I a = I a deriving Show instance Monad I where return x = I x (I x) >>= f = f x fail i = error "lookup failed" printOut :: Show a => I a -> String printOut (I x) = show x Exceptions Exceptions • mechanism for interrupting normal control flow in program • signalling exceptional condition • exception: typed, diagnostic identifier 1. typed: you can define your own kinds of exception 2. diagnostic: you can tell something about the error Exceptions – Realisation function f returns something – or fails • possibility 1: return Nothing • possibility 2: wrap every function application in a case to find out whether result is returned or exception • possibility 3: mechanism in language exception mechanisms: 1. exit(1) / atexit(:::) 2. goto 3. setjmp/longjmp 4. raise/jump (catch/throw) and variations 5. callcc continuations • Attention: user might be interested in order of errors! 1. scenario1: division by zero prior to allocation fail assumption: i=0 ) trying to allocate 1 memory ) 1 error 2. scenario2: allocation fail prior to division by zero assumption: < 512=i RAM available ^ j=0 ) 2 errors Exceptions - Order matters! • example: int i = ..., j = ...; malloc (512MB/i); ... int k = i/j; • situation: 1. allocation fail and 2. division by zero Exceptions - Order matters! • example: int i = ..., j = ...; malloc (512MB/i); ... int k = i/j; • situation: 1. allocation fail and 2. division by zero • Attention: user might be interested in order of errors! 1. scenario1: division by zero prior to allocation fail assumption: i=0 ) trying to allocate 1 memory ) 1 error 2. scenario2: allocation fail prior to division by zero assumption: < 512=i RAM available ^ j=0 ) 2 errors Exception Monad module MonError where data E a = Error String | Ok a deriving Show instance Monad E where return x = Ok x m >>= f = case m of Error s -> Error s Ok x -> f x fail s = Error s printOut :: Show a => E a -> String printOut (Error s)
Details
-
File Typepdf
-
Upload Time-
-
Content LanguagesEnglish
-
Upload UserAnonymous/Not logged-in
-
File Pages42 Page
-
File Size-