0% found this document useful (0 votes)
5 views36 pages

CS571-sp24-lecture18

The document contains lecture notes from CS 571 discussing tail recursion, continuation-passing style (CPS), and the state monad in Haskell. It includes examples of Haskell functions and their CPS transformations, as well as an overview of functional programming concepts and the lambda calculus. Additionally, it addresses the advantages and disadvantages of functional programming, along with the core elements of Haskell and the operational semantics of lambda calculus.

Uploaded by

s.rohithvardhan
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PPTX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
5 views36 pages

CS571-sp24-lecture18

The document contains lecture notes from CS 571 discussing tail recursion, continuation-passing style (CPS), and the state monad in Haskell. It includes examples of Haskell functions and their CPS transformations, as well as an overview of functional programming concepts and the lambda calculus. Additionally, it addresses the advantages and disadvantages of functional programming, along with the core elements of Haskell and the operational semantics of lambda calculus.

Uploaded by

s.rohithvardhan
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PPTX, PDF, TXT or read online on Scribd
You are on page 1/ 36

CS 571 Lecture 18

April 15, 2024


Worksheet Solutions
Tail Recursion Question


CPS Question a)
hailstone x =
if (x == 1) then 0
else if (mod x 2) == 0 then (hailstone (x/2)) + 1
else (hailstone ((x*3)+1)) + 1
CPS Answer a)
hailstone x k =
if (x == 1) then k 0
else if (mod x 2) == 0 then
hailstone (x/2) (\r -> k (r + 1))
else (hailstone ((x*3)+1)) (\r -> k (r + 1))
CPS Question b)
myAppend lst1 lst2 =
if lst1 == [] then lst2
else (head lst1) : myAppend (tail lst1) lst2

myReverse lst =
if lst == [] then []
else myAppend (myReverse (tail lst)
(Cons (head lst) MyEmpty))
CPS Answer b)
myAppend lst1 lst2 k =
if lst1 == [] then k lst2
else myAppend (tail lst1) lst2
(\x -> k ((head lst1) : x))
myReverse lst k =
if lst == [] then k []
else myReverse (tail lst) (\x ->
(myAppend x (Cons (head lst) MyEmpty))
(\y -> k y))
State Monad Follow-up
IO as a Monad
State Monad
newtype StackState a = MkStackState ([Int] -> (a, [Int]))
instance Monad StackState where
(>>=) :: m a -> (a -> m b) -> m b
return :: a -> m a

pop :: StackState Int


pop = MkStackState (\(x:xs) -> (x, xs))

push :: Int -> StackState ()


push x = MkStackState (\xs -> ((), x:xs))

stackManip :: [Int] -> (Int, [Int]) stackManip’ :: StackState Int


stackManip stack = stackManip’ = do
let push 3
(_, _ <- pop
newStack1) = push 3 stack pop
(_,
newStack2) = pop newStack1
in
IO as a Monad
IO as a Monad
hello =
do
_ <- putStrLn "Hello, what's your name?"
name <- getLine
_ <- putStrLn ("Hello " ++ name ++ "!”)

*Main> hello
Hello, what's your name?
Tim
Hello Tim!
*Main> :type hello
hello :: IO ()
*Main> :type putStrLn
putStrLn :: String -> IO ()
*Main> :type getLine getLine :: IO String *Main>
IO as a Monad
hello =
do
putStrLn "Hello, what's your name?"
name <- getLine
putStrLn ("Hello " ++ name ++ "!”)

*Main> hello
Hello, what's your name?
Tim
Hello Tim!
*Main> :type hello
hello :: IO ()
*Main> :type putStrLn
putStrLn :: String -> IO ()
*Main> :type getLine getLine :: IO String *Main>
IO as a Monad
main :: IO ()
Outer Layer
IO
getInfo :: IO [Person] compTaxes :: Person -> IO Taxes

parseData :: String -> Person compDeps :: [Person] -> [Person]

compAvg :: Fractional a => [a] -> a


Inner Layer
computeAux :: Person -> Person
non-IO
... ... ... ... ...

... ...
IO as a Monad
Input/Output gets “wrapped up” as an IO action.

An IO a performs some I/O, and returns a value of type a.

getName :: IO () putStrLn :: String -> IO ()


getName = do
putStrLn "What is your name?" getLine :: IO String
name :: String name <- getLine
putStrLn $ "Hello " ++ name

We can “unwrap” only inside another IO action.


IO as a Monad type String = [Char]

“Hello” :: String
What happens if we write:
(++) :: [a] -> [a] -> [a]
> "Hello, " ++ getLine
getLine :: IO String

<interactive>:10:14: error:
• Couldn't match expected type ‘[Char]’
with actual type ‘IO String’
• In the second argument of ‘(++)’, namely
‘getLine’
In the expression: "Hello, " ++ getLine
In an equation for ‘it’: it = "Hello, " ++
getLine
Functional Programming Summary
• Functional Programming: everything is a function.
• Advantages
• Simple language constructs
• Mathematical style of programming
• Strong type system
• Algebraic Data Types
• Type Classes
• Disadvantages
• Performance
• Challenging to represent stateful computation
The Lambda Calculus
Haskell
0, 1, 2, ..., +, -, ...

True, False, if e then e else e

let bindings where fun f x = e


e1 e2
patterns
guards
\x -> e
lists
What lies in the core of Haskell?
0, 1, 2, ..., +, -, ...

True, False, if e then e else e

let bindings where fun f x = e

patterns
? e1 e2
guards
\x -> e
lists
Candidates?
• booleans and if/then/else
• integers
• Lists
• Let bindings
• functions and function applications
• Patterns
• ...
The Core of Haskell

x
\x -> e
e1 e 2
The Core of Haskell

-calculus
-calculus is Turing-complete

-calculus Turing machine

x
\x -> e
e1 e 2
=
-calculus Overview
• The -calculus is all about minimalism
• Using only function definitions and calls, we can represent all
programming language constructs
• We have already seen how to implement let
• But, there are many more challenging things to implement
• Booleans
• Integers + Arithmetic
• Pairs for compound data types
• Recursion
Abstract Syntax of the -Calculus
• x
• variable/name
• z, s, t ...

• x. e
• -abstraction
• x = formal argument, e = body; as a parsing convention, e extends as far as it can, e.g. x. y.
x y should read as x. (y. (x y)) not (x. y. x) y or x. ((y. x) y)
• \x -> x+1

• e1 e 2
• application
• left-associative (as in Haskell):
• e1 e2 e3 = (e1 e2 ) e3
• e1 e2 e3  e1 (e2 e3 )
Operational Semantics of -Calculus
• Specifies how to transform an expression into a value via a sequence
of reductions

Exprreduction E2reduction ...reduction Enreduction Value


Values and Reductions
Reductions

: -reduction

redex = reducible expression


Free vs. Bound Variables
• Given an expression e, the following function computes the set of
“free variables” (all other variables in e are “bound variables”)
-Conversion/Reduction
• Renaming bound variables when necessary
• Okay because the names of bound variables do not matter.
• Examples
Substitution
With -Conversion
• Recall

• Hence

• for a fresh variable y,


Capture-Avoiding Substitution
Example

• We have to rename bound variables as necessary.


A Longer Example
( x.  y . x y) ( x . x y) ( a.  b . a b)
( x.  z . x z) ( x . x y) ( a.  b . a b)  conversion
( z . ( x . x y) z) ( a.  b . a b)  reduction
( x . x y) ( a.  b . a b)  reduction
( a.  b . a b) y  reduction
( b . y b)  reduction
Acknowledgments
• William Hallahan
• Sungwoo Park, CS321, programming languages

You might also like