61
Programming in Haskell: Lecture 18 S P Suresh October 16, 2019 Suresh PRGH 2019: Lecture 18 October 16, 2019 1 / 18

Programming in Haskell: Lecture 18spsuresh/teaching/prgh19/lectures/lecture18.… · ProgramminginHaskell:Lecture18 SPSuresh October16,2019 Suresh PRGH2019:Lecture18 October16,2019

  • Upload
    others

  • View
    5

  • Download
    0

Embed Size (px)

Citation preview

Page 1: Programming in Haskell: Lecture 18spsuresh/teaching/prgh19/lectures/lecture18.… · ProgramminginHaskell:Lecture18 SPSuresh October16,2019 Suresh PRGH2019:Lecture18 October16,2019

Programming in Haskell: Lecture 18

S P Suresh

October 16, 2019

Suresh PRGH 2019: Lecture 18 October 16, 2019 1 / 18

Page 2: Programming in Haskell: Lecture 18spsuresh/teaching/prgh19/lectures/lecture18.… · ProgramminginHaskell:Lecture18 SPSuresh October16,2019 Suresh PRGH2019:Lecture18 October16,2019

Reading a list of integers

• Read a list of non-negative integers (one on each line and terminatedby a negative integer)

main = do {ls <- readIntList; print ls;}readIntList :: IO [Int]readIntList = do {

inp <- readLn :: IO Int;if (inp < 0) then return [];else do {l <- readIntList; return (inp:l);}

}

• What if we want to signal the end of input by some other means?• Say, input is from a file and we process each line till the file ends

Suresh PRGH 2019: Lecture 18 October 16, 2019 2 / 18

Page 3: Programming in Haskell: Lecture 18spsuresh/teaching/prgh19/lectures/lecture18.… · ProgramminginHaskell:Lecture18 SPSuresh October16,2019 Suresh PRGH2019:Lecture18 October16,2019

Reading a list of integers

• Read a list of non-negative integers (one on each line and terminatedby a negative integer)

main = do {ls <- readIntList; print ls;}readIntList :: IO [Int]readIntList = do {

inp <- readLn :: IO Int;if (inp < 0) then return [];else do {l <- readIntList; return (inp:l);}

}

• What if we want to signal the end of input by some other means?

• Say, input is from a file and we process each line till the file ends

Suresh PRGH 2019: Lecture 18 October 16, 2019 2 / 18

Page 4: Programming in Haskell: Lecture 18spsuresh/teaching/prgh19/lectures/lecture18.… · ProgramminginHaskell:Lecture18 SPSuresh October16,2019 Suresh PRGH2019:Lecture18 October16,2019

Reading a list of integers

• Read a list of non-negative integers (one on each line and terminatedby a negative integer)

main = do {ls <- readIntList; print ls;}readIntList :: IO [Int]readIntList = do {

inp <- readLn :: IO Int;if (inp < 0) then return [];else do {l <- readIntList; return (inp:l);}

}

• What if we want to signal the end of input by some other means?• Say, input is from a file and we process each line till the file ends

Suresh PRGH 2019: Lecture 18 October 16, 2019 2 / 18

Page 5: Programming in Haskell: Lecture 18spsuresh/teaching/prgh19/lectures/lecture18.… · ProgramminginHaskell:Lecture18 SPSuresh October16,2019 Suresh PRGH2019:Lecture18 October16,2019

Reading a list of integers

• Use isEOF (requires import System.IO)

import System.IOmain = do {ls <- readIntList; print ls;}readIntList = do

exitCond <- isEOFif exitCond then return [] else do {

inp <- readLn :: IO Int;l <- readIntList; return (inp:l);

}

• isEOF returns Truewhen end of file is reached• If input is provided from keyboard, indicate end of input by Ctrl-D

Suresh PRGH 2019: Lecture 18 October 16, 2019 3 / 18

Page 6: Programming in Haskell: Lecture 18spsuresh/teaching/prgh19/lectures/lecture18.… · ProgramminginHaskell:Lecture18 SPSuresh October16,2019 Suresh PRGH2019:Lecture18 October16,2019

Reading a list of integers

• Use isEOF (requires import System.IO)

import System.IOmain = do {ls <- readIntList; print ls;}readIntList = do

exitCond <- isEOFif exitCond then return [] else do {

inp <- readLn :: IO Int;l <- readIntList; return (inp:l);

}

• isEOF returns Truewhen end of file is reached

• If input is provided from keyboard, indicate end of input by Ctrl-D

Suresh PRGH 2019: Lecture 18 October 16, 2019 3 / 18

Page 7: Programming in Haskell: Lecture 18spsuresh/teaching/prgh19/lectures/lecture18.… · ProgramminginHaskell:Lecture18 SPSuresh October16,2019 Suresh PRGH2019:Lecture18 October16,2019

Reading a list of integers

• Use isEOF (requires import System.IO)

import System.IOmain = do {ls <- readIntList; print ls;}readIntList = do

exitCond <- isEOFif exitCond then return [] else do {

inp <- readLn :: IO Int;l <- readIntList; return (inp:l);

}

• isEOF returns Truewhen end of file is reached• If input is provided from keyboard, indicate end of input by Ctrl-D

Suresh PRGH 2019: Lecture 18 October 16, 2019 3 / 18

Page 8: Programming in Haskell: Lecture 18spsuresh/teaching/prgh19/lectures/lecture18.… · ProgramminginHaskell:Lecture18 SPSuresh October16,2019 Suresh PRGH2019:Lecture18 October16,2019

Repetition using forever

• Repeatedly read a list of integers on each line and print its reverse

• Use forever to repeatedly perform an action (requires importControl.Monad)• Use exitSuccess to exit the loop (requires import System.Exit)• Check when to exit using isEOF

Suresh PRGH 2019: Lecture 18 October 16, 2019 4 / 18

Page 9: Programming in Haskell: Lecture 18spsuresh/teaching/prgh19/lectures/lecture18.… · ProgramminginHaskell:Lecture18 SPSuresh October16,2019 Suresh PRGH2019:Lecture18 October16,2019

Repetition using forever

• Repeatedly read a list of integers on each line and print its reverse• Use forever to repeatedly perform an action (requires import

Control.Monad)

• Use exitSuccess to exit the loop (requires import System.Exit)• Check when to exit using isEOF

Suresh PRGH 2019: Lecture 18 October 16, 2019 4 / 18

Page 10: Programming in Haskell: Lecture 18spsuresh/teaching/prgh19/lectures/lecture18.… · ProgramminginHaskell:Lecture18 SPSuresh October16,2019 Suresh PRGH2019:Lecture18 October16,2019

Repetition using forever

• Repeatedly read a list of integers on each line and print its reverse• Use forever to repeatedly perform an action (requires import

Control.Monad)• Use exitSuccess to exit the loop (requires import System.Exit)

• Check when to exit using isEOF

Suresh PRGH 2019: Lecture 18 October 16, 2019 4 / 18

Page 11: Programming in Haskell: Lecture 18spsuresh/teaching/prgh19/lectures/lecture18.… · ProgramminginHaskell:Lecture18 SPSuresh October16,2019 Suresh PRGH2019:Lecture18 October16,2019

Repetition using forever

• Repeatedly read a list of integers on each line and print its reverse• Use forever to repeatedly perform an action (requires import

Control.Monad)• Use exitSuccess to exit the loop (requires import System.Exit)• Check when to exit using isEOF

Suresh PRGH 2019: Lecture 18 October 16, 2019 4 / 18

Page 12: Programming in Haskell: Lecture 18spsuresh/teaching/prgh19/lectures/lecture18.… · ProgramminginHaskell:Lecture18 SPSuresh October16,2019 Suresh PRGH2019:Lecture18 October16,2019

Repetition using forever

• Repeatedly read a list of integers on each line and print its reverseimport System.IOimport System.Exitimport Control.Monadmain = forever $ do {

exitCond <- isEOF;if exitCond then exitSuccess else do {

inList <- readLn :: IO [Int];print (reverse inList);

}}

Suresh PRGH 2019: Lecture 18 October 16, 2019 5 / 18

Page 13: Programming in Haskell: Lecture 18spsuresh/teaching/prgh19/lectures/lecture18.… · ProgramminginHaskell:Lecture18 SPSuresh October16,2019 Suresh PRGH2019:Lecture18 October16,2019

Repetition using forever

• Convenient to use when along with forever to handle the exit case(requires import Control.Monad)

import System.IOimport System.Exitimport Control.Monadmain = forever $ do {

exitCond <- isEOF;when exitCond exitSuccess;inList <- readLn :: IO [Int];print (reverse inList);

}

Suresh PRGH 2019: Lecture 18 October 16, 2019 6 / 18

Page 14: Programming in Haskell: Lecture 18spsuresh/teaching/prgh19/lectures/lecture18.… · ProgramminginHaskell:Lecture18 SPSuresh October16,2019 Suresh PRGH2019:Lecture18 October16,2019

Themagic of interact

• The cleanest way of processing input is interact (requires System.IO)interact :: (String -> String) -> IO ()

• interact f applies f (a string function) to the entire input, andproduces the entire output to the screen• But Haskell is lazy!

• So only the portion of the input that is needed to produce a line ofoutput is consumed• No waiting for user to provide the whole input• The line of output is printed to stdout• Rest of the input is processed (including waiting for user to provideinput)• Truly interactive!

Suresh PRGH 2019: Lecture 18 October 16, 2019 7 / 18

Page 15: Programming in Haskell: Lecture 18spsuresh/teaching/prgh19/lectures/lecture18.… · ProgramminginHaskell:Lecture18 SPSuresh October16,2019 Suresh PRGH2019:Lecture18 October16,2019

Themagic of interact

• The cleanest way of processing input is interact (requires System.IO)interact :: (String -> String) -> IO ()

• interact f applies f (a string function) to the entire input, andproduces the entire output to the screen

• But Haskell is lazy!

• So only the portion of the input that is needed to produce a line ofoutput is consumed• No waiting for user to provide the whole input• The line of output is printed to stdout• Rest of the input is processed (including waiting for user to provideinput)• Truly interactive!

Suresh PRGH 2019: Lecture 18 October 16, 2019 7 / 18

Page 16: Programming in Haskell: Lecture 18spsuresh/teaching/prgh19/lectures/lecture18.… · ProgramminginHaskell:Lecture18 SPSuresh October16,2019 Suresh PRGH2019:Lecture18 October16,2019

Themagic of interact

• The cleanest way of processing input is interact (requires System.IO)interact :: (String -> String) -> IO ()

• interact f applies f (a string function) to the entire input, andproduces the entire output to the screen• But Haskell is lazy!

• So only the portion of the input that is needed to produce a line ofoutput is consumed• No waiting for user to provide the whole input• The line of output is printed to stdout• Rest of the input is processed (including waiting for user to provideinput)• Truly interactive!

Suresh PRGH 2019: Lecture 18 October 16, 2019 7 / 18

Page 17: Programming in Haskell: Lecture 18spsuresh/teaching/prgh19/lectures/lecture18.… · ProgramminginHaskell:Lecture18 SPSuresh October16,2019 Suresh PRGH2019:Lecture18 October16,2019

Themagic of interact

• The cleanest way of processing input is interact (requires System.IO)interact :: (String -> String) -> IO ()

• interact f applies f (a string function) to the entire input, andproduces the entire output to the screen• But Haskell is lazy!• So only the portion of the input that is needed to produce a line ofoutput is consumed

• No waiting for user to provide the whole input• The line of output is printed to stdout• Rest of the input is processed (including waiting for user to provideinput)• Truly interactive!

Suresh PRGH 2019: Lecture 18 October 16, 2019 7 / 18

Page 18: Programming in Haskell: Lecture 18spsuresh/teaching/prgh19/lectures/lecture18.… · ProgramminginHaskell:Lecture18 SPSuresh October16,2019 Suresh PRGH2019:Lecture18 October16,2019

Themagic of interact

• The cleanest way of processing input is interact (requires System.IO)interact :: (String -> String) -> IO ()

• interact f applies f (a string function) to the entire input, andproduces the entire output to the screen• But Haskell is lazy!• So only the portion of the input that is needed to produce a line ofoutput is consumed• No waiting for user to provide the whole input

• The line of output is printed to stdout• Rest of the input is processed (including waiting for user to provideinput)• Truly interactive!

Suresh PRGH 2019: Lecture 18 October 16, 2019 7 / 18

Page 19: Programming in Haskell: Lecture 18spsuresh/teaching/prgh19/lectures/lecture18.… · ProgramminginHaskell:Lecture18 SPSuresh October16,2019 Suresh PRGH2019:Lecture18 October16,2019

Themagic of interact

• The cleanest way of processing input is interact (requires System.IO)interact :: (String -> String) -> IO ()

• interact f applies f (a string function) to the entire input, andproduces the entire output to the screen• But Haskell is lazy!• So only the portion of the input that is needed to produce a line ofoutput is consumed• No waiting for user to provide the whole input• The line of output is printed to stdout

• Rest of the input is processed (including waiting for user to provideinput)• Truly interactive!

Suresh PRGH 2019: Lecture 18 October 16, 2019 7 / 18

Page 20: Programming in Haskell: Lecture 18spsuresh/teaching/prgh19/lectures/lecture18.… · ProgramminginHaskell:Lecture18 SPSuresh October16,2019 Suresh PRGH2019:Lecture18 October16,2019

Themagic of interact

• The cleanest way of processing input is interact (requires System.IO)interact :: (String -> String) -> IO ()

• interact f applies f (a string function) to the entire input, andproduces the entire output to the screen• But Haskell is lazy!• So only the portion of the input that is needed to produce a line ofoutput is consumed• No waiting for user to provide the whole input• The line of output is printed to stdout• Rest of the input is processed (including waiting for user to provideinput)

• Truly interactive!

Suresh PRGH 2019: Lecture 18 October 16, 2019 7 / 18

Page 21: Programming in Haskell: Lecture 18spsuresh/teaching/prgh19/lectures/lecture18.… · ProgramminginHaskell:Lecture18 SPSuresh October16,2019 Suresh PRGH2019:Lecture18 October16,2019

Themagic of interact

• The cleanest way of processing input is interact (requires System.IO)interact :: (String -> String) -> IO ()

• interact f applies f (a string function) to the entire input, andproduces the entire output to the screen• But Haskell is lazy!• So only the portion of the input that is needed to produce a line ofoutput is consumed• No waiting for user to provide the whole input• The line of output is printed to stdout• Rest of the input is processed (including waiting for user to provideinput)• Truly interactive!Suresh PRGH 2019: Lecture 18 October 16, 2019 7 / 18

Page 22: Programming in Haskell: Lecture 18spsuresh/teaching/prgh19/lectures/lecture18.… · ProgramminginHaskell:Lecture18 SPSuresh October16,2019 Suresh PRGH2019:Lecture18 October16,2019

Themagic of interact

• Typically f is a function that processes one line of input

• Produces output corresponding to that line of input• The library functions lines and unlines come to the rescue

lines "One\nTwo\nThree" = ["One", "Two", "Three"]unlines ["One", "Two", "Three"] = "One\nTwo\nThree\n"

• Typical use of interactmain = interact (unlines . map f . lines)

• Localises input-output to one line of code• f is a pure function

Suresh PRGH 2019: Lecture 18 October 16, 2019 8 / 18

Page 23: Programming in Haskell: Lecture 18spsuresh/teaching/prgh19/lectures/lecture18.… · ProgramminginHaskell:Lecture18 SPSuresh October16,2019 Suresh PRGH2019:Lecture18 October16,2019

Themagic of interact

• Typically f is a function that processes one line of input• Produces output corresponding to that line of input

• The library functions lines and unlines come to the rescuelines "One\nTwo\nThree" = ["One", "Two", "Three"]unlines ["One", "Two", "Three"] = "One\nTwo\nThree\n"

• Typical use of interactmain = interact (unlines . map f . lines)

• Localises input-output to one line of code• f is a pure function

Suresh PRGH 2019: Lecture 18 October 16, 2019 8 / 18

Page 24: Programming in Haskell: Lecture 18spsuresh/teaching/prgh19/lectures/lecture18.… · ProgramminginHaskell:Lecture18 SPSuresh October16,2019 Suresh PRGH2019:Lecture18 October16,2019

Themagic of interact

• Typically f is a function that processes one line of input• Produces output corresponding to that line of input• The library functions lines and unlines come to the rescue

lines "One\nTwo\nThree" = ["One", "Two", "Three"]unlines ["One", "Two", "Three"] = "One\nTwo\nThree\n"

• Typical use of interactmain = interact (unlines . map f . lines)

• Localises input-output to one line of code• f is a pure function

Suresh PRGH 2019: Lecture 18 October 16, 2019 8 / 18

Page 25: Programming in Haskell: Lecture 18spsuresh/teaching/prgh19/lectures/lecture18.… · ProgramminginHaskell:Lecture18 SPSuresh October16,2019 Suresh PRGH2019:Lecture18 October16,2019

Themagic of interact

• Typically f is a function that processes one line of input• Produces output corresponding to that line of input• The library functions lines and unlines come to the rescue

lines "One\nTwo\nThree" = ["One", "Two", "Three"]unlines ["One", "Two", "Three"] = "One\nTwo\nThree\n"

• Typical use of interactmain = interact (unlines . map f . lines)

• Localises input-output to one line of code• f is a pure function

Suresh PRGH 2019: Lecture 18 October 16, 2019 8 / 18

Page 26: Programming in Haskell: Lecture 18spsuresh/teaching/prgh19/lectures/lecture18.… · ProgramminginHaskell:Lecture18 SPSuresh October16,2019 Suresh PRGH2019:Lecture18 October16,2019

Themagic of interact

• Typically f is a function that processes one line of input• Produces output corresponding to that line of input• The library functions lines and unlines come to the rescue

lines "One\nTwo\nThree" = ["One", "Two", "Three"]unlines ["One", "Two", "Three"] = "One\nTwo\nThree\n"

• Typical use of interactmain = interact (unlines . map f . lines)

• Localises input-output to one line of code

• f is a pure function

Suresh PRGH 2019: Lecture 18 October 16, 2019 8 / 18

Page 27: Programming in Haskell: Lecture 18spsuresh/teaching/prgh19/lectures/lecture18.… · ProgramminginHaskell:Lecture18 SPSuresh October16,2019 Suresh PRGH2019:Lecture18 October16,2019

Themagic of interact

• Typically f is a function that processes one line of input• Produces output corresponding to that line of input• The library functions lines and unlines come to the rescue

lines "One\nTwo\nThree" = ["One", "Two", "Three"]unlines ["One", "Two", "Three"] = "One\nTwo\nThree\n"

• Typical use of interactmain = interact (unlines . map f . lines)

• Localises input-output to one line of code• f is a pure function

Suresh PRGH 2019: Lecture 18 October 16, 2019 8 / 18

Page 28: Programming in Haskell: Lecture 18spsuresh/teaching/prgh19/lectures/lecture18.… · ProgramminginHaskell:Lecture18 SPSuresh October16,2019 Suresh PRGH2019:Lecture18 October16,2019

Themagic of interact

• Typical use of interactmain = interact (unlines . map f . lines)

• Equivalent to the following:main = forever $ do {

exitCond <- isEOF;when exitCond exitSuccess;inp <- getLine;putStrLn $ f inp;

}

Suresh PRGH 2019: Lecture 18 October 16, 2019 9 / 18

Page 29: Programming in Haskell: Lecture 18spsuresh/teaching/prgh19/lectures/lecture18.… · ProgramminginHaskell:Lecture18 SPSuresh October16,2019 Suresh PRGH2019:Lecture18 October16,2019

Themagic of interact

• Typical use of interactmain = interact (unlines . map f . lines)

• Equivalent to the following:main = forever $ do {

exitCond <- isEOF;when exitCond exitSuccess;inp <- getLine;putStrLn $ f inp;

}

Suresh PRGH 2019: Lecture 18 October 16, 2019 9 / 18

Page 30: Programming in Haskell: Lecture 18spsuresh/teaching/prgh19/lectures/lecture18.… · ProgramminginHaskell:Lecture18 SPSuresh October16,2019 Suresh PRGH2019:Lecture18 October16,2019

Themagic of interact

• Repeatedly read a list of integers on each line and print its reverse

• Using interactimport System.IOmain = interact (unlines . map f . lines)

f :: String -> Stringf inp = show (reverse (read inp :: [Int]))

• f is required to be of type String -> String

• Hence we apply read to the input first, process it, and then apply showat the end

Suresh PRGH 2019: Lecture 18 October 16, 2019 10 / 18

Page 31: Programming in Haskell: Lecture 18spsuresh/teaching/prgh19/lectures/lecture18.… · ProgramminginHaskell:Lecture18 SPSuresh October16,2019 Suresh PRGH2019:Lecture18 October16,2019

Themagic of interact

• Repeatedly read a list of integers on each line and print its reverse• Using interact

import System.IOmain = interact (unlines . map f . lines)

f :: String -> Stringf inp = show (reverse (read inp :: [Int]))

• f is required to be of type String -> String

• Hence we apply read to the input first, process it, and then apply showat the end

Suresh PRGH 2019: Lecture 18 October 16, 2019 10 / 18

Page 32: Programming in Haskell: Lecture 18spsuresh/teaching/prgh19/lectures/lecture18.… · ProgramminginHaskell:Lecture18 SPSuresh October16,2019 Suresh PRGH2019:Lecture18 October16,2019

Themagic of interact

• Repeatedly read a list of integers on each line and print its reverse• Using interact

import System.IOmain = interact (unlines . map f . lines)

f :: String -> Stringf inp = show (reverse (read inp :: [Int]))

• f is required to be of type String -> String

• Hence we apply read to the input first, process it, and then apply showat the end

Suresh PRGH 2019: Lecture 18 October 16, 2019 10 / 18

Page 33: Programming in Haskell: Lecture 18spsuresh/teaching/prgh19/lectures/lecture18.… · ProgramminginHaskell:Lecture18 SPSuresh October16,2019 Suresh PRGH2019:Lecture18 October16,2019

Themagic of interact

• Repeatedly read a list of integers on each line and print its reverse• Using interact

import System.IOmain = interact (unlines . map f . lines)

f :: String -> Stringf inp = show (reverse (read inp :: [Int]))

• f is required to be of type String -> String

• Hence we apply read to the input first, process it, and then apply showat the end

Suresh PRGH 2019: Lecture 18 October 16, 2019 10 / 18

Page 34: Programming in Haskell: Lecture 18spsuresh/teaching/prgh19/lectures/lecture18.… · ProgramminginHaskell:Lecture18 SPSuresh October16,2019 Suresh PRGH2019:Lecture18 October16,2019

The bind operator

• Two fundamental functions used to construct and combine actionsreturn :: a -> IO a(>>=) :: IO a -> (a -> IO b) -> IO b

• Execution of act1 >>= act2

• executes act1• unboxes and extracts the return value (of type a)• executes act2, perhaps using the previously extracted value

• The return value of act2 is returned by the combined action

Suresh PRGH 2019: Lecture 18 October 16, 2019 11 / 18

Page 35: Programming in Haskell: Lecture 18spsuresh/teaching/prgh19/lectures/lecture18.… · ProgramminginHaskell:Lecture18 SPSuresh October16,2019 Suresh PRGH2019:Lecture18 October16,2019

The bind operator

• Two fundamental functions used to construct and combine actionsreturn :: a -> IO a(>>=) :: IO a -> (a -> IO b) -> IO b

• Execution of act1 >>= act2

• executes act1• unboxes and extracts the return value (of type a)• executes act2, perhaps using the previously extracted value

• The return value of act2 is returned by the combined action

Suresh PRGH 2019: Lecture 18 October 16, 2019 11 / 18

Page 36: Programming in Haskell: Lecture 18spsuresh/teaching/prgh19/lectures/lecture18.… · ProgramminginHaskell:Lecture18 SPSuresh October16,2019 Suresh PRGH2019:Lecture18 October16,2019

The bind operator

• Two fundamental functions used to construct and combine actionsreturn :: a -> IO a(>>=) :: IO a -> (a -> IO b) -> IO b

• Execution of act1 >>= act2• executes act1

• unboxes and extracts the return value (of type a)• executes act2, perhaps using the previously extracted value

• The return value of act2 is returned by the combined action

Suresh PRGH 2019: Lecture 18 October 16, 2019 11 / 18

Page 37: Programming in Haskell: Lecture 18spsuresh/teaching/prgh19/lectures/lecture18.… · ProgramminginHaskell:Lecture18 SPSuresh October16,2019 Suresh PRGH2019:Lecture18 October16,2019

The bind operator

• Two fundamental functions used to construct and combine actionsreturn :: a -> IO a(>>=) :: IO a -> (a -> IO b) -> IO b

• Execution of act1 >>= act2• executes act1• unboxes and extracts the return value (of type a)

• executes act2, perhaps using the previously extracted value• The return value of act2 is returned by the combined action

Suresh PRGH 2019: Lecture 18 October 16, 2019 11 / 18

Page 38: Programming in Haskell: Lecture 18spsuresh/teaching/prgh19/lectures/lecture18.… · ProgramminginHaskell:Lecture18 SPSuresh October16,2019 Suresh PRGH2019:Lecture18 October16,2019

The bind operator

• Two fundamental functions used to construct and combine actionsreturn :: a -> IO a(>>=) :: IO a -> (a -> IO b) -> IO b

• Execution of act1 >>= act2• executes act1• unboxes and extracts the return value (of type a)• executes act2, perhaps using the previously extracted value

• The return value of act2 is returned by the combined action

Suresh PRGH 2019: Lecture 18 October 16, 2019 11 / 18

Page 39: Programming in Haskell: Lecture 18spsuresh/teaching/prgh19/lectures/lecture18.… · ProgramminginHaskell:Lecture18 SPSuresh October16,2019 Suresh PRGH2019:Lecture18 October16,2019

The bind operator

• Two fundamental functions used to construct and combine actionsreturn :: a -> IO a(>>=) :: IO a -> (a -> IO b) -> IO b

• Execution of act1 >>= act2• executes act1• unboxes and extracts the return value (of type a)• executes act2, perhaps using the previously extracted value

• The return value of act2 is returned by the combined action

Suresh PRGH 2019: Lecture 18 October 16, 2019 11 / 18

Page 40: Programming in Haskell: Lecture 18spsuresh/teaching/prgh19/lectures/lecture18.… · ProgramminginHaskell:Lecture18 SPSuresh October16,2019 Suresh PRGH2019:Lecture18 October16,2019

The bind operator

• Actually, return and (>>=) are functions common to all monads

• IO is an example of a monad• Many other type constructors we have already seen produce monads –

[], Maybe&c.• Wewill (perhaps!) see other examples of monads later• Functions like readLn, putStrLn, print&c. are specific to the IOmonad

Suresh PRGH 2019: Lecture 18 October 16, 2019 12 / 18

Page 41: Programming in Haskell: Lecture 18spsuresh/teaching/prgh19/lectures/lecture18.… · ProgramminginHaskell:Lecture18 SPSuresh October16,2019 Suresh PRGH2019:Lecture18 October16,2019

The bind operator

• Actually, return and (>>=) are functions common to all monads• IO is an example of a monad

• Many other type constructors we have already seen produce monads –[], Maybe&c.• Wewill (perhaps!) see other examples of monads later• Functions like readLn, putStrLn, print&c. are specific to the IOmonad

Suresh PRGH 2019: Lecture 18 October 16, 2019 12 / 18

Page 42: Programming in Haskell: Lecture 18spsuresh/teaching/prgh19/lectures/lecture18.… · ProgramminginHaskell:Lecture18 SPSuresh October16,2019 Suresh PRGH2019:Lecture18 October16,2019

The bind operator

• Actually, return and (>>=) are functions common to all monads• IO is an example of a monad• Many other type constructors we have already seen produce monads –

[], Maybe&c.

• Wewill (perhaps!) see other examples of monads later• Functions like readLn, putStrLn, print&c. are specific to the IOmonad

Suresh PRGH 2019: Lecture 18 October 16, 2019 12 / 18

Page 43: Programming in Haskell: Lecture 18spsuresh/teaching/prgh19/lectures/lecture18.… · ProgramminginHaskell:Lecture18 SPSuresh October16,2019 Suresh PRGH2019:Lecture18 October16,2019

The bind operator

• Actually, return and (>>=) are functions common to all monads• IO is an example of a monad• Many other type constructors we have already seen produce monads –

[], Maybe&c.• Wewill (perhaps!) see other examples of monads later

• Functions like readLn, putStrLn, print&c. are specific to the IOmonad

Suresh PRGH 2019: Lecture 18 October 16, 2019 12 / 18

Page 44: Programming in Haskell: Lecture 18spsuresh/teaching/prgh19/lectures/lecture18.… · ProgramminginHaskell:Lecture18 SPSuresh October16,2019 Suresh PRGH2019:Lecture18 October16,2019

The bind operator

• Actually, return and (>>=) are functions common to all monads• IO is an example of a monad• Many other type constructors we have already seen produce monads –

[], Maybe&c.• Wewill (perhaps!) see other examples of monads later• Functions like readLn, putStrLn, print&c. are specific to the IOmonad

Suresh PRGH 2019: Lecture 18 October 16, 2019 12 / 18

Page 45: Programming in Haskell: Lecture 18spsuresh/teaching/prgh19/lectures/lecture18.… · ProgramminginHaskell:Lecture18 SPSuresh October16,2019 Suresh PRGH2019:Lecture18 October16,2019

Using bind

• Read a line and print itgetLine >>= putStrLn

• Read a line and print its lengthgetLine :: IO Stringprint :: Show a => a -> IO ()

getLine >>= (\str ->print (length str))

Suresh PRGH 2019: Lecture 18 October 16, 2019 13 / 18

Page 46: Programming in Haskell: Lecture 18spsuresh/teaching/prgh19/lectures/lecture18.… · ProgramminginHaskell:Lecture18 SPSuresh October16,2019 Suresh PRGH2019:Lecture18 October16,2019

Using bind

• Read a line and print itgetLine >>= putStrLn

• Read a line and print its lengthgetLine :: IO Stringprint :: Show a => a -> IO ()

getLine >>= (\str ->print (length str))

Suresh PRGH 2019: Lecture 18 October 16, 2019 13 / 18

Page 47: Programming in Haskell: Lecture 18spsuresh/teaching/prgh19/lectures/lecture18.… · ProgramminginHaskell:Lecture18 SPSuresh October16,2019 Suresh PRGH2019:Lecture18 October16,2019

Using bind

• Read a line and print its length twicegetLine >>= (\str ->

print (length str) >>=print (length str))

• This produces a type error

• The second (>>=) expects a second argument of type () -> IO c• But print x is of type IO ()

• Correct code!getLine >>= (\str -> print (length str) >>=

(\str' -> print (length str)))

Suresh PRGH 2019: Lecture 18 October 16, 2019 14 / 18

Page 48: Programming in Haskell: Lecture 18spsuresh/teaching/prgh19/lectures/lecture18.… · ProgramminginHaskell:Lecture18 SPSuresh October16,2019 Suresh PRGH2019:Lecture18 October16,2019

Using bind

• Read a line and print its length twicegetLine >>= (\str ->

print (length str) >>=print (length str))

• This produces a type error

• The second (>>=) expects a second argument of type () -> IO c• But print x is of type IO ()

• Correct code!getLine >>= (\str -> print (length str) >>=

(\str' -> print (length str)))

Suresh PRGH 2019: Lecture 18 October 16, 2019 14 / 18

Page 49: Programming in Haskell: Lecture 18spsuresh/teaching/prgh19/lectures/lecture18.… · ProgramminginHaskell:Lecture18 SPSuresh October16,2019 Suresh PRGH2019:Lecture18 October16,2019

Using bind

• Read a line and print its length twicegetLine >>= (\str ->

print (length str) >>=print (length str))

• This produces a type error• The second (>>=) expects a second argument of type () -> IO c

• But print x is of type IO ()

• Correct code!getLine >>= (\str -> print (length str) >>=

(\str' -> print (length str)))

Suresh PRGH 2019: Lecture 18 October 16, 2019 14 / 18

Page 50: Programming in Haskell: Lecture 18spsuresh/teaching/prgh19/lectures/lecture18.… · ProgramminginHaskell:Lecture18 SPSuresh October16,2019 Suresh PRGH2019:Lecture18 October16,2019

Using bind

• Read a line and print its length twicegetLine >>= (\str ->

print (length str) >>=print (length str))

• This produces a type error• The second (>>=) expects a second argument of type () -> IO c• But print x is of type IO ()

• Correct code!getLine >>= (\str -> print (length str) >>=

(\str' -> print (length str)))

Suresh PRGH 2019: Lecture 18 October 16, 2019 14 / 18

Page 51: Programming in Haskell: Lecture 18spsuresh/teaching/prgh19/lectures/lecture18.… · ProgramminginHaskell:Lecture18 SPSuresh October16,2019 Suresh PRGH2019:Lecture18 October16,2019

Using bind

• Read a line and print its length twicegetLine >>= (\str ->

print (length str) >>=print (length str))

• This produces a type error• The second (>>=) expects a second argument of type () -> IO c• But print x is of type IO ()

• Correct code!getLine >>= (\str -> print (length str) >>=

(\str' -> print (length str)))

Suresh PRGH 2019: Lecture 18 October 16, 2019 14 / 18

Page 52: Programming in Haskell: Lecture 18spsuresh/teaching/prgh19/lectures/lecture18.… · ProgramminginHaskell:Lecture18 SPSuresh October16,2019 Suresh PRGH2019:Lecture18 October16,2019

Bind without arguments

• A simpler version of the previous action:getLine >>= (\str ->

print (length str) >>print (length str)

)

• If we do not want to unbox and use the result of the preceding action,we use (>>)• act1 >> act2 is equivalent to the following (where the name n is notused in act2):

act1 >>= (\n -> act2)

Suresh PRGH 2019: Lecture 18 October 16, 2019 15 / 18

Page 53: Programming in Haskell: Lecture 18spsuresh/teaching/prgh19/lectures/lecture18.… · ProgramminginHaskell:Lecture18 SPSuresh October16,2019 Suresh PRGH2019:Lecture18 October16,2019

Bind without arguments

• A simpler version of the previous action:getLine >>= (\str ->

print (length str) >>print (length str)

)

• If we do not want to unbox and use the result of the preceding action,we use (>>)

• act1 >> act2 is equivalent to the following (where the name n is notused in act2):

act1 >>= (\n -> act2)

Suresh PRGH 2019: Lecture 18 October 16, 2019 15 / 18

Page 54: Programming in Haskell: Lecture 18spsuresh/teaching/prgh19/lectures/lecture18.… · ProgramminginHaskell:Lecture18 SPSuresh October16,2019 Suresh PRGH2019:Lecture18 October16,2019

Bind without arguments

• A simpler version of the previous action:getLine >>= (\str ->

print (length str) >>print (length str)

)

• If we do not want to unbox and use the result of the preceding action,we use (>>)• act1 >> act2 is equivalent to the following (where the name n is notused in act2):

act1 >>= (\n -> act2)

Suresh PRGH 2019: Lecture 18 October 16, 2019 15 / 18

Page 55: Programming in Haskell: Lecture 18spsuresh/teaching/prgh19/lectures/lecture18.… · ProgramminginHaskell:Lecture18 SPSuresh October16,2019 Suresh PRGH2019:Lecture18 October16,2019

Bind without arguments

Consider the definitions (where y does not occur in exp2)

f x = exp1g y = exp2h = g (f 10)

• f 10 is not evaluated when computing h

• Given actions act1 and act2, executing act1 >> act2 always executesact1, even though its return value is not used in act2• The operators (>>=) and (>>) force execution of both the arguments,the left one first and then the right one

Suresh PRGH 2019: Lecture 18 October 16, 2019 16 / 18

Page 56: Programming in Haskell: Lecture 18spsuresh/teaching/prgh19/lectures/lecture18.… · ProgramminginHaskell:Lecture18 SPSuresh October16,2019 Suresh PRGH2019:Lecture18 October16,2019

Bind without arguments

Consider the definitions (where y does not occur in exp2)

f x = exp1g y = exp2h = g (f 10)

• f 10 is not evaluated when computing h• Given actions act1 and act2, executing act1 >> act2 always executes

act1, even though its return value is not used in act2

• The operators (>>=) and (>>) force execution of both the arguments,the left one first and then the right one

Suresh PRGH 2019: Lecture 18 October 16, 2019 16 / 18

Page 57: Programming in Haskell: Lecture 18spsuresh/teaching/prgh19/lectures/lecture18.… · ProgramminginHaskell:Lecture18 SPSuresh October16,2019 Suresh PRGH2019:Lecture18 October16,2019

Bind without arguments

Consider the definitions (where y does not occur in exp2)

f x = exp1g y = exp2h = g (f 10)

• f 10 is not evaluated when computing h• Given actions act1 and act2, executing act1 >> act2 always executes

act1, even though its return value is not used in act2• The operators (>>=) and (>>) force execution of both the arguments,the left one first and then the right one

Suresh PRGH 2019: Lecture 18 October 16, 2019 16 / 18

Page 58: Programming in Haskell: Lecture 18spsuresh/teaching/prgh19/lectures/lecture18.… · ProgramminginHaskell:Lecture18 SPSuresh October16,2019 Suresh PRGH2019:Lecture18 October16,2019

do is syntactic sugar

• The do blocks introduced earlier can be translated in terms of (>>=)and (>>)

• A single action needs no dodo {putStrLn "Hello world!";}

translates to

putStrLn "Hello world!"

Suresh PRGH 2019: Lecture 18 October 16, 2019 17 / 18

Page 59: Programming in Haskell: Lecture 18spsuresh/teaching/prgh19/lectures/lecture18.… · ProgramminginHaskell:Lecture18 SPSuresh October16,2019 Suresh PRGH2019:Lecture18 October16,2019

do is syntactic sugar

• The do blocks introduced earlier can be translated in terms of (>>=)and (>>)• A single action needs no do

do {putStrLn "Hello world!";}

translates to

putStrLn "Hello world!"

Suresh PRGH 2019: Lecture 18 October 16, 2019 17 / 18

Page 60: Programming in Haskell: Lecture 18spsuresh/teaching/prgh19/lectures/lecture18.… · ProgramminginHaskell:Lecture18 SPSuresh October16,2019 Suresh PRGH2019:Lecture18 October16,2019

do is syntactic sugar

• If there is no <- in the first action, we use >>do {act1; S}

translates to

act1 >> do {S}

• If there is <- in the first action, we use >>=do {n <- act1; S}

translates to

act1 >>= \n -> do {S}

Suresh PRGH 2019: Lecture 18 October 16, 2019 18 / 18

Page 61: Programming in Haskell: Lecture 18spsuresh/teaching/prgh19/lectures/lecture18.… · ProgramminginHaskell:Lecture18 SPSuresh October16,2019 Suresh PRGH2019:Lecture18 October16,2019

do is syntactic sugar

• If there is no <- in the first action, we use >>do {act1; S}

translates to

act1 >> do {S}

• If there is <- in the first action, we use >>=do {n <- act1; S}

translates to

act1 >>= \n -> do {S}

Suresh PRGH 2019: Lecture 18 October 16, 2019 18 / 18