рдирд┐рд░рдВрддрд░рддрд╛ рдПрдХ рдирд┐рд╢реНрдЪрд┐рдд рд╕рдордп рдкрд░ рдХрд╛рд░реНрдпрдХреНрд░рдо рдХреА рд╕реНрдерд┐рддрд┐ рд╣реИ, рдЬрд┐рд╕рдХрд╛ рдЙрдкрдпреЛрдЧ рд╣рдо рдЙрд╕ рд╕реНрдерд┐рддрд┐ рдореЗрдВ рд▓реМрдЯрдиреЗ рдХреЗ рд▓рд┐рдП рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред
рдирд┐рд░рдВрддрд░рддрд╛рдУрдВ рдХреА рдорджрдж рд╕реЗ, рдЖрдк рдЕрдкрд╡рд╛рдж рд╣реИрдВрдбрд▓рд┐рдВрдЧ, рдЧреЛрдЯреЛ рдХреА рд╕рдорд╛рдирддрд╛ рдФрд░ рдХрдИ рдЕрдиреНрдп рдЪреАрдЬреЛрдВ рдХреЛ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рд┐рдд рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ, рдЬреЛ рдЕрдирд┐рд╡рд╛рд░реНрдп рдирд┐рд░реНрдорд╛рдг рдХреА рдпрд╛рдж рджрд┐рд▓рд╛рддреЗ рд╣реИрдВред
рдЗрд╕рдХреЗ рдЕрд▓рд╛рд╡рд╛, рдПрдХреНрд╕рдЯреЗрдВрд╢рди рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ, рдЖрдк рдЕрдирд╛рд╡рд╢реНрдпрдХ "рд░реИрдкреНрд╕" рдФрд░ рдкреИрдЯрд░реНрди рдорд┐рд▓рд╛рди рдХреЛ рд╣рдЯрд╛рдХрд░ рдХрд╛рд░реНрдпрдХреНрд░рдо рдХреЗ рдкреНрд░рджрд░реНрд╢рди рдореЗрдВ рд╕реБрдзрд╛рд░ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред
рдЗрд╕ рд▓реЗрдЦ рдореЗрдВ рдореИрдВ рдЖрдкрдХреЛ рдмрддрд╛рдКрдВрдЧрд╛ рдХрд┐ рдЖрдк рд╣рд╛рд╕реНрдХреЗрд▓ рдореЗрдВ рдПрдХреНрд╕рдЯреЗрдВрд╢рди рдХреИрд╕реЗ рд▓рд╛рдЧреВ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ, рдФрд░ рдХреБрдЫ рджрд┐рд▓рдЪрд╕реНрдк рдлрд╝рдВрдХреНрд╢рди рджрд┐рдЦрд╛ рд╕рдХрддреЗ рд╣реИрдВ рдЬреЛ рдЙрдирдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рддреЗ рд╣реИрдВред
рдирд┐рд░рдВрддрд░рддрд╛ рд╢реИрд▓реА рдкреНрд░реЛрдЧреНрд░рд╛рдорд┐рдВрдЧ
рд╢реБрд░реВ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдЖрдЗрдП рджреЗрдЦреЗрдВ рдХрд┐ рдирд┐рд░рдВрддрд░рддрд╛ рдХреА рд╢реИрд▓реА рдореЗрдВ рдирд┐рд░рдВрддрд░рддрд╛ рдФрд░ рдкреНрд░реЛрдЧреНрд░рд╛рдорд┐рдВрдЧ рдХреНрдпрд╛ рд╣реИрдВред
рд╕рд╛рдорд╛рдиреНрдп рдХрд╛рд░реНрдп:
square :: Int -> Int
square x = x*x
incr :: Int -> Int
incr x = x+1
func :: Int -> Int
func x = square (incr x)
рдФрд░ рдЕрдм рд╕реАрдХреНрд╡рд▓ рдХреА рд╢реИрд▓реА рдореЗрдВ:
square_cps :: Int -> (Int -> r) -> r square_cps xk = k (x*x) incr_cps :: Int -> (Int -> r) -> r incr_cps xk = k (x+1) func_cps :: Int -> (Int -> r) -> r func_cps xk = incr_cps x $ \inc -> square_cps inc $ \sq -> k sq
рдЕрдм рдлрд╝рдВрдХреНрд╢рди, рд╕реНрд╡рдпрдВ рддрд░реНрдХреЛрдВ рдХреЗ рдЕрд▓рд╛рд╡рд╛, рдлрд╝рдВрдХреНрд╢рди рдХреЗ рд▓рд┐рдП рдПрдХ рдЗрдирдкреБрдЯ рд▓реЗрддреЗ рд╣реИрдВ рдЬрд┐рд╕реЗ рдкрд░рд┐рдгрд╛рдо рдкрд░ рд▓рд╛рдЧреВ рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛ред рдпрд╣ рдПрдХ рдирд┐рд░рдВрддрд░рддрд╛ рд╣реИред
рдирд┐рд░рдВрддрд░рддрд╛рдУрдВ рдХреА рдорджрдж рд╕реЗ, рд╣рдо рдлрд╝рдВрдХреНрд╢рди рдХрдиреЗрдХреНрдЯ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ, рдЬреЛ рдХрд┐
func_cps
рдореЗрдВ рд╣реЛрддрд╛ рд╣реИред рд╕рдмрд╕реЗ рдкрд╣рд▓реЗ,
incr_cps
рдХреЛ
incr_cps
, рдФрд░ рдЗрд╕рдХреЗ рдкрд░рд┐рдгрд╛рдо "рдирд┐рд░рдВрддрд░рддрд╛"
(\inc -> ...)
рдореЗрдВ
square_cps
рд╣реИ, рдлрд┐рд░
square_cps
рдЬрд┐рд╕рдХрд╛ рдкрд░рд┐рдгрд╛рдо рдирд┐рд░рдВрддрд░рддрд╛
(\sq -> ...)
рдХреЛ рджрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рдЬреЛ рдЕрдВрдд рдореЗрдВ рд╕рдмрд╕реЗ рдмрд╛рд╣рд░реА рдирд┐рд░рдВрддрд░рддрд╛
k
рдХреЛ рджрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред
рдпрд╣рд╛рдБ рдирд┐рд░рдВрддрд░рддрд╛ рдкреНрд░рдХрд╛рд░
(Int -> r)
рдХреНрдпреЛрдВрдХрд┐ рдпрд╣ рдЖрд╡рд╢реНрдпрдХ рдирд╣реАрдВ рд╣реИ рдХрд┐ рдирд┐рд░рдВрддрд░рддрд╛
Int
рд╡рд╛рдкрд╕ рдЖрдПрдЧреАред
рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдкрд░рд┐рдгрд╛рдо рдХреЛ рдХрдВрд╕реЛрд▓ рдкрд░ рдкреНрд░рд┐рдВрдЯ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рд╣рдо
print
рдХреЛ рдПрдХ рдирд┐рд░рдВрддрд░рддрд╛ рдХреЗ рд░реВрдк рдореЗрдВ рдкрд╛рд╕ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ:
main = func_cps 5 print
рдореЛрдирд╛рдж рдХрдВрдЯ
рдЖрдк рд╕реАрдХреНрд╡реЗрд▓ рдХреА рд╢реИрд▓реА рдореЗрдВ рдХреБрдЫ рдкреИрдЯрд░реНрди рджреЗрдЦ рд╕рдХрддреЗ рд╣реИрдВред
рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рд╕рд░рд▓ рдХрд╛рд░реНрдп, рдЬреИрд╕реЗ рдХрд┐
square_cps
рдФрд░
incr_cps
, рд╣рдордиреЗ рдПрдХ рд╕рдорд╛рди рддрд░реАрдХреЗ рд╕реЗ рдШреЛрд╖рд┐рдд рдХрд┐рдпрд╛:
function ... = \k -> k (...)
рдФрд░ рд╣рдордиреЗ рдЙрдиреНрд╣реЗрдВ рдЗрд╕ рддрд░рд╣ рд╕реЗ рдЬреЛрдбрд╝рд╛:
fun1 ... $ \r1 -> fun2 ... $ \r2 -> ...
рдпрд╣ рд╕рдм рд╣рдореЗрдВ рднрд┐рдХреНрд╖реБрдУрдВ рдХреА рдпрд╛рдж рджрд┐рд▓рд╛рддрд╛ рд╣реИ, рдкрд╣рд▓рд╛ рдЙрджрд╛рд╣рд░рдг
return
рд╕рдорд╛рди рд╣реИ, рдФрд░ рджреВрд╕рд░рд╛
>>=
ред
рд╣рдо рдЗрд╕ рд░реВрдк рдореЗрдВ рдорда рдХрд╛ рдкрд░рд┐рдЪрдп рджреЗрддреЗ рд╣реИрдВ:
newtype Cont ra = Cont { runCont :: (a -> r) -> r }
рд▓реЗрдХрд┐рди рдХреНрдпреЛрдВ
(a -> r) -> r
?
рддрдереНрдп рдпрд╣ рд╣реИ рдХрд┐ рдЬрдм рд╣рдордиреЗ рдирд┐рд░рдВрддрд░рддрд╛ рдХреА рд╢реИрд▓реА рдореЗрдВ рдлрд╝рдВрдХреНрд╢рди рд▓рд┐рдЦрд╛ рдерд╛, рддреЛ рдкреНрд░рддреНрдпреЗрдХ рдлрд╝рдВрдХреНрд╢рди рдиреЗ рдПрдХ рдЕрддрд┐рд░рд┐рдХреНрдд рдкреИрд░рд╛рдореАрдЯрд░ рд▓рд┐рдпрд╛ рдЬреЛ рдЧрдгрдирд╛ рдЬрд╛рд░реА рд░рдЦрддрд╛ рд╣реИред
рдпрджрд┐ рд╣рдо рддрд░реНрдХреЛрдВ рдХреЗ рд╕рд╛рде рдЬрд╛рд░реА рд░рдЦрдиреЗ рдХреА рд╢реИрд▓реА рдореЗрдВ рдПрдХ рдлрд╝рдВрдХреНрд╢рди рдХреЛ "рднрд░реЗрдВ" (рдирд┐рд░рдВрддрд░рддрд╛ рддрдХ), рддреЛ рдЗрд╕рдХрд╛ рдкреНрд░рдХрд╛рд░ рд╣реЛрдЧрд╛
(a -> r) -> r
, рдЬрд╣рд╛рдВ рдлрд╝рдВрдХреНрд╢рди рдХреЗ рдкрд░рд┐рдгрд╛рдо рдХрд╛ рдкреНрд░рдХрд╛рд░ рд╣реИ, рдЕрдЧрд░ рд╣рдо рдЗрд╕реЗ рдЬрд╛рд░реА рд░рдЦрдиреЗ рдХреЗ рд▓рд┐рдП рдмрд┐рдирд╛ рдкрд╛рд╕ рд▓реМрдЯреЗ рд╣реИрдВ, рдФрд░
r
- рдкрд░рд┐рдгрд╛рдо рдХреЗ рдкреНрд░рдХрд╛рд░ рдЬреЛ рдирд┐рд░рдВрддрд░рддрд╛ рд╡рд╛рдкрд╕ рдЖрдПрдЧреА:
> :t square_cps 5
square_cps :: (Int -> r) -> r
рдЪрд▓рд┐рдП рдХрдВрдЯ рдХреЛ рдореЛрдирд╛рдб рдмрдирд╛рдиреЗ рдХреА рдХреЛрд╢рд┐рд╢ рдХрд░рддреЗ рд╣реИрдВред
instance Monad (Cont r) where return n = Cont $ \k -> kn ...
return n
рдПрдХ рдРрд╕рд╛ рдХрдВрдЯреЗрдВрдЯ рд╣реИ рдЬреЛ рддреБрд░рдВрдд рдкреНрд░рд╛рдкреНрдд рд╣реЛрдиреЗ рд╡рд╛рд▓реЗ рдПрди рдкрд░ рд▓рд╛рдЧреВ рд╣реЛрддрд╛ рд╣реИред
m >>= f = Cont $ \k -> runCont m (\a -> runCont (fa) k)
m >>= f
рд╡рд╣
runCont
рдЬреЛ рд╢реБрд░реВ рд╣реЛрддрд╛ рд╣реИ (
runCont
рдмрд╕ "
runCont
" рдХрдВрдЯ, рдлрдВрдХреНрд╢рди рдХреЛ
runCont
рдХрд░рддрд╛ рд╣реИ)
m
рдирд┐рд░рдВрддрд░рддрд╛ рдХреЗ рд╕рд╛рде
(\a -> runCont (fa) k)
, рдЬреЛ рдЧрдгрдирд╛ рдХрд╛ рдкрд░рд┐рдгрд╛рдо рд╣реЛ рд╕рдХрддрд╛ рд╣реИ, рдФрд░ рдЗрд╕реЗ рдЕрд╕рд╛рдЗрди рдХрд░реЗрдВ (рдпрд╛ рд╣реЛ рд╕рдХрддрд╛ рд╣реИ) рдФрд░ рдпрд╣ рдирд╣реАрдВ рдорд┐рд▓реЗрдЧрд╛, рдХреНрдпреЛрдВрдХрд┐ рдлрд╝рдВрдХреНрд╢рди рдирд┐рд░рдВрддрд░рддрд╛ рдХреЛ рдЕрдирджреЗрдЦрд╛ рдХрд░ рд╕рдХрддрд╛ рд╣реИ)ред рдлрд┐рд░, рджреВрд╕рд░реЗ рдХрдВрдЯ рдХреЛ рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП
f
рдкрд░ рд▓рд╛рдЧреВ рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛, рдЬреЛ рдХрд┐
k
рдХреЗ рд╕рдмрд╕реЗ рдмрд╛рд╣рд░реА рдирд┐рд░рдВрддрд░рддрд╛ рдХреЗ рд╕рд╛рде рд▓реЙрдиреНрдЪ рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛ред
рд╣рдо рдЕрдкрдиреЗ рдХрд╛рд░реНрдпрдХреНрд░рдо рдХреЛ рдорда рдХреЗ рдЙрдкрдпреЛрдЧ рд╕реЗ рдлрд┐рд░ рд╕реЗ рд▓рд┐рдЦрддреЗ рд╣реИрдВ:
square_Cont :: Int -> Cont r Int
square_Cont x = return (x*x)
incr_Cont :: Int -> Cont r Int
incr_Cont x = return (x+1)
func_Cont :: Int -> Cont r Int func_Cont x = do inc <- incr_Cont x sq <- square_Cont inc return sq
main = runCont (func_Cont 5) print
рдЕрдм рд╕рдм рдХреБрдЫ рдмрд╣реБрдд рд╕рд╛рдл рджрд┐рдЦрддрд╛ рд╣реИред
рдХрдВрдЯ рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рдиреЗ рд╡рд╛рд▓реЗ рдХрд╛рд░реНрдпреЛрдВ рдХреЛ рдЖрдЧреЗ рдмрдврд╝рд╛рддреЗ рд╣реИрдВред
callCC
рдЖрдЗрдП рдПрдХ рд╕рд░рд▓ рдЙрджрд╛рд╣рд░рдг рд╕реЗ рд╢реБрд░реВ рдХрд░реЗрдВ:
square :: Int -> Cont r Int
square n = callCC $ \k -> k (n*n)
рдХреНрдпрд╛ рдмреЗрдХрд╛рд░ рдХрд╛рд░реНрдп? рдРрд╕рд╛ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдпрд╣ рдХрдВрдЯ рдХрдВрд╕реНрдЯреНрд░рдХреНрдЯрд░ рдХрд╛ рдкрд░реНрдпрд╛рдп рд╣реИред
рд▓реЗрдХрд┐рди рдпрд╣ рдЗрддрдирд╛ рдЖрд╕рд╛рди рдирд╣реАрдВ рд╣реИред рдЖрдЗрдП рджреЗрдЦреЗрдВ
callCC
рдХреЗ рдкреНрд░рдХрд╛рд░:
callCC :: ((a -> Cont rb) -> Cont ra) -> Cont ra
рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ,
callCC
рдПрдХ рдлрд╝рдВрдХреНрд╢рди рд▓реЗрддрд╛ рд╣реИ рдЬреЛ рдПрдХ рдЕрдиреНрдп рдлрд╝рдВрдХреНрд╢рди рд▓реЗрддрд╛ рд╣реИ, рдЬреИрд╕реЗ
(a -> Cont rb)
рдФрд░ рд░рд┐рдЯрд░реНрди
Cont ra
ред рдЕрд░реНрдерд╛рдд,
k (n*n)
рд╣рдорд╛рд░реЗ рдЙрджрд╛рд╣рд░рдг рдореЗрдВ
Cont r Int
рдкреНрд░рдХрд╛рд░ рдХрд╛ рд╣реИред
рдореИрдВ
callCC
рдХреНрдпрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХрддрд╛ рд╣реВрдВ? рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдХрд┐рд╕реА рдлрд╝рдВрдХреНрд╢рди рд╕реЗ рдЬрд▓реНрджреА рд╕реЗ рдмрд╛рд╣рд░ рдирд┐рдХрд▓рдиреЗ рдХреЗ рд▓рд┐рдП:
import Control.Monad (when) hehe :: Int -> Cont r String hehe n = callCC $ \exit -> do let fac = product [1..n] when (n > 7) $ exit "OVER 9000" return $ show fac main = do n <- fmap read getLine runCont (hehe n) putStrLn
рдЪрд▓реЛ рд╣рдорд╛рд░реЗ рдХрд╛рд░реНрдпрдХреНрд░рдо рдХреА рдХреЛрд╢рд┐рд╢ рдХрд░реЗрдВ:
> main
3
6
> main
10
OVER 9000
рдпрд╣ рдХрд╛рд░реНрдпрдХреНрд░рдо рддрдереНрдп рдХреА рдЧрдгрдирд╛ рдХрд░рддрд╛ рд╣реИ, рдФрд░ рдЕрдЧрд░ рдпрд╣ 9000 рд╕реЗ рдЕрдзрд┐рдХ рдирд┐рдХрд▓рд╛, рддреЛ рдпрд╣ "OVER 9000" рд╕рдВрджреЗрд╢ рд▓реМрдЯрд╛рддрд╛ рд╣реИ, рдФрд░ рдпрджрд┐ рдирд╣реАрдВ, рддреЛ рдмрд╕ рдЗрд╕рдХрд╛ рдореВрд▓реНрдпред
рдпрд╣рд╛рдВ рд╣рдордиреЗ
exit
рдЙрдкрдпреЛрдЧ рдЕрдирд┐рд╡рд╛рд░реНрдп рднрд╛рд╖рд╛рдУрдВ рдореЗрдВ рдХрд┐рдпрд╛ - рдЙрдиреНрд╣реЛрдВрдиреЗ рдЧрдгрдирд╛ рдХреЛ рдмрд╛рдзрд┐рдд рдХрд┐рдпрд╛ рдФрд░ рдПрдХ рдЕрд▓рдЧ рдкрд░рд┐рдгрд╛рдо рдирд┐рдХрд╛рд▓рд╛ред
рдиреЗрд╕реНрдЯреЗрдб рдХреЙрд▓рд╕реАрд╕реА рдмреНрд▓реЙрдХреЛрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдирд╛ рднреА рд╕рдВрднрд╡ рд╣реИ:
bar :: String -> Cont r String bar s = do callCC $ \exit1 -> do let ws = words s names = foldl (\ac -> a ++ ", " ++ c) (head ws) (tail ws) r' <- callCC $ \exit2 -> do when (null ws) $ exit1 "No people" when (length ws == 1) $ exit2 "There is " return "There are: " return $ r' ++ names main = do ns <- getLine runCont (bar ns) putStrLn
рдЖрдЗрдП рдХреЛрд╢рд┐рд╢ рдХрд░рддреЗ рд╣реИрдВ:
> main
No people
> main
Bob
There is Bob
> main
Bob Alice
There are: Bob, Alice
рдпрджрд┐ рдирд╛рдореЛрдВ рдХреА рд╕реВрдЪреА рдЦрд╛рд▓реА рд╣реИ, рддреЛ рд╣рдо рдмрд╛рд╣рд░
exit1 "No people"
, рдЖрдВрддрд░рд┐рдХ рдмреНрд▓реЙрдХ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ "рдХреВрдж" рдХрд╣рддреЗ рд╣реИрдВред
рдпрджрд┐ рдХреЗрд╡рд▓ рдПрдХ рд╡реНрдпрдХреНрддрд┐ рд╣реИ, рддреЛ рд╣рдо "рд╡рд╣рд╛рдБ" рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реИрдВ, рдпрджрд┐ рдЙрдирдореЗрдВ рд╕реЗ рдмрд╣реБрдд рд╕рд╛рд░реЗ рд╣реИрдВ, рддреЛ "рд╡рд╣рд╛рдБ рд╣реИрдВ:"ред
рдзреНрдпрд╛рди рджреЗрдВ рдХрд┐ рдЬрдм рдЧрдгрдирд╛ рдХреЙрд▓рд╕реАрд╕реА рдмреНрд▓реЙрдХ рдореЗрдВ рд╡рд╛рдкрд╕ рдкрд╣реБрдВрдЪрддреА рд╣реИ, рддреЛ рдкрд░рд┐рдгрд╛рдо рд╣рдореЗрд╢рд╛ рдХреА рддрд░рд╣ рд╡рд╛рдкрд╕ рдЖ рдЬрд╛рддрд╛ рд╣реИред
рддреЛ
callCC
рдлрд╝рдВрдХреНрд╢рди рдХреИрд╕реЗ
callCC
? рдЖрдЗрдП рджреЗрдЦреЗрдВ:
callCC f = Cont $ \k -> runCont (f (\a -> Cont $ \_ -> ka)) k
рдпрд╣ рдХрдВрдЯреЗрдВрдЯ рдореЗрдВ рдирд┐рд░рдВрддрд░рддрд╛ рдХреА рд╢реИрд▓реА рдореЗрдВ рдлрд╝рдВрдХреНрд╢рди рдХреЛ рд▓рдкреЗрдЯрдиреЗ рдХреЗ рд╕рд╛рде, рд╕рд╛рдорд╛рдиреНрдп рддрд░реАрдХреЗ рд╕реЗ рд╢реБрд░реВ рд╣реЛрддрд╛ рд╣реИред рддрдм
(f (\a -> Cont $ \_ -> ka))
k
рдирд┐рд░рдВрддрд░рддрд╛ рдХреЗ рд╕рд╛рде рд╢реБрд░реВ рд╣реЛрддрд╛ рд╣реИред
(\a -> Cont $ \_ -> ka)
рдПрдХ рдРрд╕рд╛ рдлрдВрдХреНрд╢рди рд╣реИ рдЬреЛ рдХреБрдЫ рд▓реЗрддрд╛ рд╣реИ рдФрд░ рдПрдХ рдХреЙрдиреНрдЯ рдХреЛ рд▓реМрдЯрд╛рддрд╛ рд╣реИ, рдЗрд╕рдХреА рдирд┐рд░рдВрддрд░рддрд╛ рдХреЛ рдЕрдирджреЗрдЦрд╛ рдХрд░рддрд╛ рд╣реИ рдФрд░ рдЗрд╕рдХреЗ рдмрдЬрд╛рдп рдЗрд╕рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддрд╛ рд╣реИред
рдЖрдЗрдП рджреЗрдЦреЗрдВ рдХрд┐ рдпрд╣ рдХреИрд╕реЗ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИ:
square n = callCC $ \k -> k (n*n)
= Cont $ \k' -> runCont ((\k -> k (n*n)) (\a -> Cont $ \_ -> k' a)) k'
= Cont $ \k' -> runCont ((\a -> Cont $ \_ -> k' a) (n*n)) k'
= Cont $ \k' -> runCont (Cont $ \_ -> k' (n*n)) k'
= Cont $ \k' -> (\_ -> k' (n*n)) k'
= Cont $ \k' -> k' (n*n)
рд╕рдм рдХреБрдЫ рд╡реИрд╕рд╛ рд╣реА рд╣реИ рдЬреИрд╕рд╛ рд╣рдореЗрдВ рдЙрдореНрдореАрдж рдереАред рдЕрдзрд┐рдХ рдЬрдЯрд┐рд▓ рдорд╛рдорд▓реЗ рдкрд░ рд╡рд┐рдЪрд╛рд░ рдХрд░реЗрдВ:
hehe :: Int -> Cont r String hehe n = callCC $ \exit -> do let fac = product [1..n] when (n > 7) $ exit "OVER 9000" return $ show fac = callCC $ \exit -> (when (n > 7) $ exit "OVER 9000") >> (return $ show (product [1..n])) -- let = Cont $ \k -> runCont ((\exit -> (when (n > 7) $ exit "OVER 9000") >> (return $ show (product [1..n]))) (\a -> Cont $ \_ -> ka)) k = Cont $ \k -> runCont ((when (n > 7) $ (\a -> Cont $ \_ -> ka) "OVER 9000") >> (return $ show (product [1..n]))) k = Cont $ \k -> runCont ((when (n > 7) $ (Cont $ \_ -> k "OVER 9000")) >> (return $ show (product [1..n]))) k
рдЬрдм рдХрд╛рдо рдХрд░рддрд╛ рд╣реИ, рддреЛ рдпрд╣ рд╡рд╛рдкрд╕ рдЖ рдЬрд╛рдПрдЧрд╛
(Cont $ \_ -> k "OVER 9000")
ред рдпрд╣ рдХрдВрдЯ рдЕрдкрдиреЗ рдирд┐рд░рдВрддрд░рддрд╛ рдХрд╛ рдЙрдкрдпреЛрдЧ рдирд╣реАрдВ рдХрд░рддрд╛ рд╣реИ, рдЬрд┐рд╕рдХрд╛ рдЕрд░реНрде рд╣реИ рдХрд┐ рдмрд╛рдХреА рдХреЛрдб рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдирд╣реАрдВ рдХрд░реЗрдЧрд╛ред
getCC
getCC
рдФрд░
getCC'
рдлрд╝рдВрдХреНрд╢рди рд╣рдореЗрдВ рд╡рд░реНрддрдорд╛рди рдирд┐рд░рдВрддрд░рддрд╛ рдХреЛ "рдкреНрд░рд╛рдкреНрдд" рдХрд░рдиреЗ рдФрд░ рдХрд╛рд░реНрдпрдХреНрд░рдо рдХреЗ рдкрд┐рдЫрд▓реЗ рд░рд╛рдЬреНрдп рдореЗрдВ рд╡рд╛рдкрд╕ рдЬрд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддреЗ рд╣реИрдВред
рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП:
foo :: Int -> Cont r String foo s = do (i, back) <- getCC' s when (i < 20) $ back (i*2) return $ show i
foo
рдЕрдкрдиреЗ рддрд░реНрдХ рдХреЛ рддрдм рддрдХ рджреЛрдЧреБрдирд╛ рдХрд░рддрд╛ рд╣реИ рдЬрдм рддрдХ рдХрд┐ рд╡рд╣ 20 рд╕реЗ рдЕрдзрд┐рдХ рдпрд╛ рдмрд░рд╛рдмрд░ рди рд╣реЛ рдЬрд╛рдПред
> runCont (foo 5) id
"20"
> runCont (foo 3) id
"24"
> runCont (foo 2) id
"32"
(i, back) <- getCC' s
-
i
s
i
рдорд╛рди рдкреНрд░рджрд╛рди рдХрд░рддрд╛ рд╣реИ рдФрд░ рдЗрд╕ рд╕реНрдерд╛рди рдкрд░ рдПрдХ "рд▓рд┐рдВрдХ" рдмрдирд╛рддрд╛ рд╣реИред
back (i*2)
- рдкрд┐рдЫрд▓реА рд╕реНрдерд┐рддрд┐ рдореЗрдВ рд▓реМрдЯрддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди
i
i*2
рдмрд░рд╛рдмрд░ред
рдпрд╣ рд╕рдм рджреГрдврд╝рддрд╛ рд╕реЗ рдЧреЛрдЯреЛ рдЬреИрд╕рд╛ рд╣реИ, рд╣рд╛рд▓рд╛рдВрдХрд┐ рдпрд╣рд╛рдВ рд╣рдо рдХреЗрд╡рд▓ рдкрд┐рдЫрд▓реЗ рд░рд╛рдЬреНрдпреЛрдВ рдореЗрдВ рдЬрд╛ рд╕рдХрддреЗ рд╣реИрдВред
getCC'
рдлрд╝рдВрдХреНрд╢рди рдЗрд╕ рддрд░рд╣ рдШреЛрд╖рд┐рдд рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ:
getCC' :: t -> Cont r (t, t -> Cont ra) getCC' x0 = callCC (\c -> let fx = c (x, f) in return (x0, f))
рдЖрдЗрдП рдЗрд╕реЗ рдЬрд╛рдирдиреЗ рдХреА рдХреЛрд╢рд┐рд╢ рдХрд░реЗрдВред рдЖрдЗрдП рдЗрд╕реЗ рд╕рд░рд▓ рдХрд░рдирд╛ рд╢реБрд░реВ рдХрд░реЗрдВ:
getCC' x0 = Cont $ \k -> runCont ((\c -> let fx = c (x, f) in return (x0, f)) (\a -> Cont $ \_ -> ka)) k
= Cont $ \k -> runCont (let fx = (\a -> Cont $ \_ -> ka) (x, f) in return (x0, f)) k
= Cont $ \k -> runCont (let fx = Cont $ \_ -> k (x, f) in return (x0, f)) k
= Cont $ \k -> runCont (let fx = Cont $ \_ -> k (x, f) in Cont $ \k' -> k' (x0, f)) k
= Cont $ \k -> let fx = Cont $ \_ -> k (x, f) in k (x0, f)
f
рдлрд╝рдВрдХреНрд╢рди рдЕрдкрдиреЗ рддрд░реНрдХ рдХреА рдПрдХ рдЬреЛрдбрд╝реА рдХреЛ рд▓рд╛рдЧреВ рдХрд░рддрд╛ рд╣реИ рдФрд░ рдЦреБрдж рдХреЛ рдмрд╛рд╣рд░реА (getCC'shnom) рдирд┐рд░рдВрддрд░рддрд╛ рдкрд░ рд▓рд╛рдЧреВ рдХрд░рддрд╛ рд╣реИ, рдФрд░ рдЗрд╕реЗ рдХрдВрдЯ рдореЗрдВ рд▓рдкреЗрдЯрддрд╛ рд╣реИред
рдФрд░
k (x0, f)
- рддрд░реНрдХ
getCC'
рд╕реЗ рдЬреЛрдбрд╝реА рдХреЛ рд▓рд╛рдЧреВ рдХрд░рддрд╛ рд╣реИ
getCC'
рдФрд░ рдмрд╛рд╣рд░реА рдирд┐рд░рдВрддрд░рддрд╛ рдХреЗ рд▓рд┐рдП
f
ред
рдЬрдм рд╣рдо рдХрд╣реАрдВ рдФрд░
f
рдХреЙрд▓ рдХрд░рддреЗ рд╣реИрдВ, рддреЛ рдпрд╣ рдПрдХ
getCC'
рд▓реМрдЯрд╛рддрд╛ рд╣реИ, рд╡рд░реНрддрдорд╛рди рдирд┐рд░рдВрддрд░рддрд╛ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдирд╣реАрдВ, рдмрд▓реНрдХрд┐ рд╡рд╣ рдЬреЛ
getCC'
рд▓рд┐рдП рдЪрд╛рд▓реВ рдерд╛ред
getCC'
рдЗрд╕ рдкреНрд░рдХрд╛рд░, рд╣рдо рдкрд┐рдЫрд▓реЗ рд░рд╛рдЬреНрдп рдореЗрдВ рд╡рд╛рдкрд╕реА рдХрд░рддреЗ рд╣реИрдВред
рдЗрд╕рдХреЗ рдЕрд▓рд╛рд╡рд╛,
getCC'
рдХрд╛ рдПрдХ "рдЫреЛрдЯрд╛ рднрд╛рдИ" рд╣реИ -
getCC
, рд▓реЗрдХрд┐рди рдпрд╣ рдХреЗрд╡рд▓ ContT (Cont рдХреЗ рд▓рд┐рдП рдЯреНрд░рд╛рдВрд╕рдлрд╛рд░реНрдорд░) рдХреЗ рд╕рд╛рде рдЙрдкрдпреЛрдЧреА рд╣реИ:
import Control.Monad (when) import Control.Monad.Cont getCC :: MonadCont m => m (ma) getCC = callCC (\c -> let x = cx in return x) foo :: ContT () IO () foo = do back <- getCC liftIO $ putStr "Do you want to coninue? [y/n] " a <- liftIO $ getLine when (a == "y" || a == "Y") $ back main = runContT foo return
> main
Do you want to coninue? [y/n] y
Do you want to coninue? [y/n] y
Do you want to coninue? [y/n] n
>
рдХрд╛рд░реНрдпрдХреНрд░рдо рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдХреЛ "рдПрди" рдЬрд╡рд╛рдм рджреЗрдиреЗ рддрдХ рдЬрд╛рд░реА рд░рдЦрдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рдорд╛рдВрдЧреЗрдЧрд╛ред
рдЗрд╕рд╕реЗ рдкрддрд╛ рдЪрд▓рддрд╛ рд╣реИ рдХрд┐
getCC
рдХреЗрд╡рд▓ рдкрд┐рдЫрд▓реА рд╕реНрдерд┐рддрд┐ рдореЗрдВ рд▓реМрдЯрдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рддрд░реНрдХ рдкрд╛рд░рд┐рдд рдХрд░рдиреЗ рдХрд╛ рдЕрд╡рд╕рд░ рдирд╣реАрдВ рджреЗрддрд╛ рд╣реИред
рдореБрдЭреЗ рдХрдВрдЯ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд╣рд╛рдБ рдХрд░рдирд╛ рдЪрд╛рд╣рд┐рдП?
рдПрдХреНрд╕рдЯреЗрдВрд╢рди рдХреА рдорджрдж рд╕реЗ, рдЖрдк рд▓рдЪреАрд▓реЗ рдврдВрдЧ рд╕реЗ рдкреНрд░реЛрдЧреНрд░рд╛рдо рдХреА рдкреНрд░рдЧрддрд┐ рдХреЛ рдирд┐рдпрдВрддреНрд░рд┐рдд рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ, рдЗрд╕рдХреЗ рдкреВрд░рд╛ рд╣реЛрдиреЗ рд╕реЗ рдкрд╣рд▓реЗ рдлрд╝рдВрдХреНрд╢рди рд╕реЗ рд╡рд╛рдкрд╕ рдЖ рд╕рдХрддреЗ рд╣реИрдВ рдФрд░ рдПрдХ рдЕрдкрд╡рд╛рдж рдкреНрд░рдгрд╛рд▓реА рдмрдирд╛ рд╕рдХрддреЗ рд╣реИрдВред
рдХрд┐рд╕реА рдЕрдиреНрдп рд╕рдордп рдкрд░ рдЗрд╕реЗ рд╡рд╛рдкрд╕ рдХрд░рдХреЗ рдЧрдгрдирд╛ рдХреЛ "рдирд┐рд▓рдВрдмрд┐рдд" рдХрд░рдирд╛ рднреА рд╕рдВрднрд╡ рд╣реИ (рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рд╣рдЧреНрд╕ рд╕рдВрдЧрд╛рдорд┐рддрд┐ рдХреЛ рд▓рд╛рдЧреВ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдирд┐рд░рдВрддрд░рддрд╛ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддрд╛ рд╣реИ)ред
рдореВрд▓ рд░реВрдк рд╕реЗ, рдХреЙрдирдЯ рдХрд╛ рдЙрдкрдпреЛрдЧ рдЕрдиреНрдп рд╕рд╛рдзреБрдУрдВ рдХреЗ рд╕рд╛рде рдПрдХ рдЯреНрд░рд╛рдВрд╕рдлрд╛рд░реНрдорд░ рдХреА рддрд░рд╣ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред рдЗрд╕рд╕реЗ рдЬрдЯрд┐рд▓ рдирд┐рдпрдВрддреНрд░рдг рд╕рдВрд░рдЪрдирд╛рдУрдВ рдХреЛ рдмрдирд╛рдиреЗ рдФрд░ / рдпрд╛ рдЧрдгрдирд╛рдУрдВ рдХреЛ рддреЗрдЬ рдХрд░рдиреЗ рдореЗрдВ рдЖрд╕рд╛рдиреА рд╣реЛрддреА рд╣реИред
рдкреНрд░рдпреБрдХреНрдд рд╕рд╛рдордЧреНрд░реА рдХреА рд╕реВрдЪреА
рдирд┐рд░рдВрддрд░рддрд╛ рд╢реИрд▓реАрд╣реЙрдХреЗрд▓ рдореЗрдВ рдЧреЛрдЯреЛрд╣рд╛рд╕реНрдХреЗрд▓ рдХрд╛рд░реНрдпрдХреНрд░рдореЛрдВ рдХреЛ рддреЗрдЬ рдФрд░ рдЫреЛрдЯрд╛ рдмрдирд╛рдирд╛