Monads. Functional Programming (CS4011) Monads

Similar documents
State Monad (3D) Young Won Lim 8/31/17

Monad Overview (3B) Young Won Lim 1/16/18

Monads and all that I. Monads. John Hughes Chalmers University/Quviq AB

Background Type Classes (1B) Young Won Lim 6/28/18

Advanced Programming Handout 7. Monads and Friends (SOE Chapter 18)

Haskell & functional programming, some slightly more advanced stuff. Matteo Pradella

Background Type Classes (1B) Young Won Lim 6/14/18

Software System Design and Implementation

Monads in Haskell. Nathanael Schilling. December 12, 2014

IO Monad (3D) Young Won Lim 1/18/18

EECS 700 Functional Programming

Programming in Haskell Aug Nov 2015

1 Delimited continuations in Haskell

Monads. COS 441 Slides 16

College Functors, Applicatives

Harvard School of Engineering and Applied Sciences CS 152: Programming Languages

Informatics 1 Functional Programming 19 Tuesday 23 November IO and Monads. Philip Wadler University of Edinburgh

State Monad (3D) Young Won Lim 9/25/17

Monads seen so far: IO vs Gen

Polymorphism Overview (1A) Young Won Lim 2/20/18

I/O in Haskell. To output a character: putchar :: Char -> IO () e.g., putchar c. To output a string: putstr :: String -> IO () e.g.

Programming Languages

Haskell Monads CSC 131. Kim Bruce

CS 11 Haskell track: lecture 1

CSCE 314 Programming Languages Functors, Applicatives, and Monads

Outline. Introduction Concepts and terminology The case for static typing. Implementing a static type system Basic typing relations Adding context

Maybe Monad (3B) Young Won Lim 1/3/18

Parsing. Zhenjiang Hu. May 31, June 7, June 14, All Right Reserved. National Institute of Informatics

Informatics 1 Functional Programming Lectures 15 and 16. IO and Monads. Don Sannella University of Edinburgh

Haske k ll An introduction to Functional functional programming using Haskell Purely Lazy Example: QuickSort in Java Example: QuickSort in Haskell

Introduction to Haskell

Applicative, traversable, foldable

An introduction introduction to functional functional programming programming using usin Haskell

IO Monad (3C) Young Won Lim 1/6/18

References. Monadic I/O in Haskell. Digression, continued. Digression: Creating stand-alone Haskell Programs

CIS552: Advanced Programming

Maybe Monad (3B) Young Won Lim 12/21/17

CS 242. Fundamentals. Reading: See last slide

CS 320: Concepts of Programming Languages

CSCI-GA Scripting Languages

Monads and all that III Applicative Functors. John Hughes Chalmers University/Quviq AB

Monad (3A) Young Won Lim 8/9/17

CS 11 Haskell track: lecture 4. n This week: Monads!

CS 320: Concepts of Programming Languages

State Monad Examples (6C) Young Won Lim 9/26/18

CS 360: Programming Languages Lecture 12: More Haskell

Monad Background (3A) Young Won Lim 10/5/17

CS152: Programming Languages. Lecture 11 STLC Extensions and Related Topics. Dan Grossman Spring 2011

The story so far. Elements of Programming Languages. Pairs in various languages. Pairs

CIS 194: Homework 4. Due Wednesday, February 18, What is a Number?

Applicative, traversable, foldable

More on functional programming

Functional Programming and Haskell

CSCE 314 Programming Languages. Type System

(Co)Monads forgrad Dummies Students

Monad (1A) Young Won Lim 6/26/17

Monad class. Example: Lambda laughter. The functional IO problem. EDAN40: Functional Programming Functors and Monads

State Monad Examples (6C) Young Won Lim 9/22/18

COMP 161 Lecture Notes 16 Analyzing Search and Sort

PROGRAMMING IN HASKELL. Chapter 5 - List Comprehensions

Type Checking and Type Equality

CS 457/557: Functional Languages

CSC324 Principles of Programming Languages

Two Types of Types. Primitive Types in Java. Using Primitive Variables. Class #07: Java Primitives. Integer types.

Monads. Bonus lecture 2017 David Sands

Type families and data kinds

Developing Good Habits for Bare-Metal Programming

n n Try tutorial on front page to get started! n spring13/ n Stack Overflow!

GADTs. Wouter Swierstra. Advanced functional programming - Lecture 7. Faculty of Science Information and Computing Sciences

All About Monads A comprehensive guide to the theory and practice of monadic programming in Haskell Version 1.1.0

Monad Background (3A) Young Won Lim 11/18/17

Advanced Functional Programming

Programming in C++ Prof. Partha Pratim Das Department of Computer Science and Engineering Indian Institute of Technology, Kharagpur

Functional Programming in Haskell Prof. Madhavan Mukund and S. P. Suresh Chennai Mathematical Institute

CSC324 Principles of Programming Languages

CS 11 Haskell track: lecture 5. This week: State monads

Multi-paradigm Declarative Languages

What is it? CMSC 433 Programming Language Technologies and Paradigms Spring Approach 1. Disadvantage of Approach 1

Background Operators (1E) Young Won Lim 7/7/18

Review. CS152: Programming Languages. Lecture 11 STLC Extensions and Related Topics. Let bindings (CBV) Adding Stuff. Booleans and Conditionals

PIC 10A Objects/Classes

CS 457/557: Functional Languages

CS 209 Functional Programming

Semantic Analysis. Lecture 9. February 7, 2018

CS 320: Concepts of Programming Languages

A Study In Monads Leif Harald Karlsen Master s Thesis Autumn 2013

Fusion-powered EDSLs

Overview. Elements of Programming Languages. Evaluation order. Evaluation order

CSci 450: Org. of Programming Languages Overloading and Type Classes

COMP3151/9151 Foundations of Concurrency Lecture 8

IO Monad (3C) Young Won Lim 8/23/17

Arrow Basics. Ted Cooper CS510 Winter Here s a literate introduction to arrows and review of the basic Arrow typeclasses.

Applicatives Comparisons (2C) Young Won Lim 3/6/18

Introduction to Programming in C Department of Computer Science and Engineering. Lecture No. #17. Loops: Break Statement

Chapter 13: Reference. Why reference Typing Evaluation Store Typings Safety Notes

Side Effects (3B) Young Won Lim 11/20/17

Lecture 1: Overview

CMSC 330: Organization of Programming Languages. OCaml Imperative Programming

CMSC 330: Organization of Programming Languages. OCaml Imperative Programming

Programming with Math and Logic

Transcription:

Monads Functional Programming (CS4011) Andrew Butterfield Glenn Strong Foundations & Methods Group, Discipline of Software Systems Trinity College, University of Dublin {Andrew.Butterfield,Glenn.Strong}@cs.tcd.ie November 19, 2010 We have encountered the type IO a as a mechanism for dealing with certain kinds of computations. The type represents functions which are actions that peform side-effects. In lecture 9 the word monad was used to refer to this kind of abstraction. What s going on with those (and are they useful for anything other than IO)? Monads It doesn t take much to see the problem. Do we know what this will do: Let s remind ourselves of the issues around IO. Imagine we have functions such as: primgetchar :: Char primputchar :: Char -> () 5 For these functions to be meaningful they would be performing some side-effecting IO operations whenever they are evaluated. A clear violation of referential transparency! f1 = (getchar,getchar) How about this: f2 = let x = getchar in (x,x) If we draw the graphs of f1 and f2 we can see the problem. (, ) (, ) getchar getchar getchar But by referential transparency they should be the same value! 5 here a we are using the type () as a void type

Solutions? One solution to this problem is to require some sort of token which will enforce the evaluation we want. We can wrap up the (unsafe) primgetchar function in a (safe) function that takes into account the side effects: getchar :: World -> (Char,World) The World here is a parameter which represents the state of the world from one moment to another The actual details of how that is encoded, and of how getchar might use it are not important right now, but we assume that it is not possible to make copies of the world! Now we can write our hazardous function differently: f3 w = ( w2, (ch1,ch2) ) where (ch1, w1) = getchar w (ch2, w2) = getchar w1 Having to thread the various w parameters forces the evaluation to happen the way we want, as long as we are careful never to make more than one reference to any given state of the world. Enforcing safety Type definition for IO We need to ensure that this sort of thing never happens: f3 w = ( w2, (ch1,ch2) ) where (ch1, w1) = getchar w (ch2, w2) = getchar w We would also like to make it a bit easier to write functions that use this style (manually threading the w s around will get tedious quickly). Since all our functions will have a type similar to: World -> (a,world) we will declare a type to capture this: type IO a = World -> (a,world) (again, not worrying about what World actually is at this time) Giving the familiar looking types: getchar :: IO Char putchar :: IO ()

Joining two computations Further operations Given two computations we can write a combinator which will sequence them, safely threading the World value through in the correct manner: (>>) :: IO a -> IO b -> IO b which we can use to sequence two actions: f4 = (putchar a ) >> (putchar b ) This operator will do the first action, throw away the result, and then do the second action. We could also join two computations together passing the result of the first on to the second: (>>=) :: IO a -> (a -> IO b) -> IO b This operation is called bind. In fact, if we have bind we can write >> easily: (>>) l r = l >>= (\_ -> r) (>>>) l r = \w -> let (w1,_) = l w in r w1 Further operations The IO Monad Finally, we will need a computation which does nothing and produces a given result: return :: a -> IO a This represents a sort of unit operation. We can see the need for it when we try to combine several values: f5 = getchar >>= ( \ ch1 -> getchar >>= ( \ ch2 -> return (ch1,ch2) ) ) What we have seen so far is a possible implementation for a monad that performs IO. A monad is an abstraction which represents a computation. The computations have results (reflected in the type). The monad provides at least the basic operations: return which produces a result >>= which binds together two computations. Generally a monad will also provide a collection of primitive operations (like getchar) to make it useful.

Do notation do is just sugar! Programs written in a monadic style will typically contain long chains of >> and >>= operations. Haskell provides some syntactic sugar, called the do-notation that allows us to write the previous program as follows: f5 = do ch1 <- getchar ch2 <- getchar return (ch1,ch2) There is a mechanical translation from the do-notation form to the combinator form, which we can summarize: = do x y x >> do y do a <- x y = x >>= \a -> do y do x = x The Monad laws Any monad? In order to retain the semantics that we want any implementation of a monad is required to follow these rules: (return v >>= f) == f v f >>= return == f (x >>= f) >>= g == x >>= (\a -> f a >>= g) These laws are not checked by the compiler. But they are assumed by it! Any implementation of a monad? Yes, monads represent something fundamental in computation, the idea of connecting two computations and threading results. There are more monads than IO. For example, another monad which we have seen already is Maybe! Imagine a function: f tree = case (findentry "foo" tree) of Nothing -> Nothing Just x -> case (findentry "bar" tree) of Nothing -> Nothing Just y -> Just (x,y) We can clean this up because Maybe is a monad!

Monads in Haskell f tree = do x <- findentry "foo" tree y <- findentry "bar" tree return (x,y) The relevant definitions? return = Just (>>=) Nothing f = Nothing (>>=) (Just x) f = f x Which implies, of course, that we are using the class mechanism to implement monads. Monads in Haskell are represented by a type class: class Monad m where (>>=) :: m a -> (a -> m b) -> m b (>>) :: m a -> m b -> m b return :: a -> m a fail :: String -> m a Since >> can be defined in terms of >>= we usually only need to provide instances for return and >>=. (sidebar: The fourth member of the class is an error handling operation which takes an error message and causes the chain of functions to fail, usually by using error to halt the program). Monad State Monad Quick terminology overview: XYZ Monad : A data type XYZ which is an instance of Monad Monadic : Pertaining to monads (of a programming style or a value, usually) IO uses a monad instance to manage the state value that we represented with the word World in the previous lecture. Whenever we have a state parameter like this we could make use of the monadic style to manage it safely. This approach is so common that it is worth the time to abstract the overall pattern of managing state.

State Monad Records in Haskell A record is really just a standard data type with one constructor: First we need a data type to be the instance of Monad. The standard Haskell state data type used for this is: newtype State s a = State { runstate :: s -> (a, s) } This is a Haskell record type. data Pair a b = Pair a b To use a type like this you might provide some accessor functions: first :: (Pair a b) -> a first (Pair a _) = a second :: (Pair a b) -> b second (Pair _ b) = b Records in Haskell Records in Haskell Defining the data type as a record type is just a syntactic convenience for creating those accessors: newtype Pair a b = Pair { } first :: a, second :: b We can either create values using the usual constructor, or using the named fields: f = Pair 1 a We can look them up using the field names: h :: (Pair Int b) -> Int h p = (first p) + 1 There s also a convenient syntax for creating a new value based on an old one: newpair p = p { second = b } g = Pair { second = a, first = 1 } (notice the order doesn t matter when we use the fields).

State Instances State Instances We need to provide an instance of return to inject a value into the State monad: returnstate :: a -> State s a returnstate a = State ( \s -> (a,s) ) Alternatively: returnstate a s = State (a,s) Joining two State actions together is simple enough. We need to use runstate to extract the actual functions. bindstate :: State s a -> (a -> State s b) -> State s b bindstate m k = State ( \s -> let (a, s ) = runstate m s in runstate (k a) s ) This is enough: the other instances in the Monad class will be derived automatically. State Instances Almost all that remains is to make State an instance of the Monad class: instance Monad (State s) where return = returnstate (>>=) = bindstate Set and Get the state There is actually one more job: return will inject a value into the state monad, but it won t actually touch the state parameter itself! We need to add a couple of transitions which will set and get the state parameter: getst :: State s s getst = State $ \s -> (s, s) putst :: s -> State s () putst s = State $ \_ -> ((), s) Perhaps unsurprisingly, there is another class that we can instantiate once we have these: instance MonadState (State s) s where get = getst put = putst

Example - threading Random generators Using State data Val = Val Int Bool Char Int deriving Show makerandomvalue :: StdGen -> (Val, StdGen) makerandomvalue = let (n,g1) = randomr (1,100) g (b,g2) = random g1 (c,g3) = randomr ( a, z ) g2 (m,g4) = getone (-n, n) g3 in (Val n b c m, g4 ) Ugly, no? This is what is meant when we talk about having to thread values through a computation. A classic use of a State monad is to thread a random number generator: getany :: (Random a) => State StdGen a getany = do g <- get (x,g ) <- return $ random g put g return x Using State Using State getone :: (Random a) => (a,a) -> State StdGen a getone bounds = do g <- get (x,g ) <- return $ randomr bounds g put g return x data Val = Val Int Bool Char Int deriving Show makerandomvaluest :: StdGen -> (Val, StdGen) makerandomvaluest = runstate (do n <- getone (1,100) b <- getany c <- getone ( a, z ) m <- getone (-n, n) return (Val n b c m) )

Using it List as a monad main = do g <- getstdgen print $ fst $ makerandomvalue g print $ fst $ makerandomvaluest g The Maybe type can be thought of as a monad. Anything else? Lists! instance Monad [] where return a = [a] lst >>= f = concat (map f lst) fail _ = [] What could it mean? How does it work? Take this code: What does it mean to say that lists form a monad? It represents the type of computations that may return 0, 1, or more results. More specifically, it combines actions by applying the operations to all possible values. cart xs ys = do x <- xs y <- ys return (x,y) What will an application like cart [1,2,3] [97,98,99] do? Prelude> cart [1,2,3] [97,98,99] [(1,97),(1,98),(1,99),(2,97),(2,98),(2,99), (3,97),(3,98),(3,99)]

Some practical Monad notes Functors and Monads are closely related. When a programmer defines a Monad instance they usually define a Functor instance as well. Therefore fmap usually works on Mondaic values. Writing code which unwraps a Monadic value and then applies it right away is fairly common (and tiresome): m >>= \l -> return (sum l) In these cases we can use liftm liftm :: (Monad m) => (a -> b) -> m a -> m b liftm f m = m >>= \i -> return (f i) In fact, many more control structures are abstracted this way. There is a whole library: Control.Monad which contains such things (check out sequence_, for example, and there are nearly 30 others).