рд╣рд╛рд╕реНрдХреЗрд▓ рдореЗрдВ рдирд┐рд░рдВрддрд░рддрд╛

рдирд┐рд░рдВрддрд░рддрд╛ рдПрдХ рдирд┐рд╢реНрдЪрд┐рдд рд╕рдордп рдкрд░ рдХрд╛рд░реНрдпрдХреНрд░рдо рдХреА рд╕реНрдерд┐рддрд┐ рд╣реИ, рдЬрд┐рд╕рдХрд╛ рдЙрдкрдпреЛрдЧ рд╣рдо рдЙрд╕ рд╕реНрдерд┐рддрд┐ рдореЗрдВ рд▓реМрдЯрдиреЗ рдХреЗ рд▓рд┐рдП рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред
рдирд┐рд░рдВрддрд░рддрд╛рдУрдВ рдХреА рдорджрдж рд╕реЗ, рдЖрдк рдЕрдкрд╡рд╛рдж рд╣реИрдВрдбрд▓рд┐рдВрдЧ, рдЧреЛрдЯреЛ рдХреА рд╕рдорд╛рдирддрд╛ рдФрд░ рдХрдИ рдЕрдиреНрдп рдЪреАрдЬреЛрдВ рдХреЛ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рд┐рдд рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ, рдЬреЛ рдЕрдирд┐рд╡рд╛рд░реНрдп рдирд┐рд░реНрдорд╛рдг рдХреА рдпрд╛рдж рджрд┐рд▓рд╛рддреЗ рд╣реИрдВред
рдЗрд╕рдХреЗ рдЕрд▓рд╛рд╡рд╛, рдПрдХреНрд╕рдЯреЗрдВрд╢рди рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ, рдЖрдк рдЕрдирд╛рд╡рд╢реНрдпрдХ "рд░реИрдкреНрд╕" рдФрд░ рдкреИрдЯрд░реНрди рдорд┐рд▓рд╛рди рдХреЛ рд╣рдЯрд╛рдХрд░ рдХрд╛рд░реНрдпрдХреНрд░рдо рдХреЗ рдкреНрд░рджрд░реНрд╢рди рдореЗрдВ рд╕реБрдзрд╛рд░ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред

рдЗрд╕ рд▓реЗрдЦ рдореЗрдВ рдореИрдВ рдЖрдкрдХреЛ рдмрддрд╛рдКрдВрдЧрд╛ рдХрд┐ рдЖрдк рд╣рд╛рд╕реНрдХреЗрд▓ рдореЗрдВ рдПрдХреНрд╕рдЯреЗрдВрд╢рди рдХреИрд╕реЗ рд▓рд╛рдЧреВ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ, рдФрд░ рдХреБрдЫ рджрд┐рд▓рдЪрд╕реНрдк рдлрд╝рдВрдХреНрд╢рди рджрд┐рдЦрд╛ рд╕рдХрддреЗ рд╣реИрдВ рдЬреЛ рдЙрдирдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рддреЗ рд╣реИрдВред

рдирд┐рд░рдВрддрд░рддрд╛ рд╢реИрд▓реА рдкреНрд░реЛрдЧреНрд░рд╛рдорд┐рдВрдЧ


рд╢реБрд░реВ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдЖрдЗрдП рджреЗрдЦреЗрдВ рдХрд┐ рдирд┐рд░рдВрддрд░рддрд╛ рдХреА рд╢реИрд▓реА рдореЗрдВ рдирд┐рд░рдВрддрд░рддрд╛ рдФрд░ рдкреНрд░реЛрдЧреНрд░рд╛рдорд┐рдВрдЧ рдХреНрдпрд╛ рд╣реИрдВред

рд╕рд╛рдорд╛рдиреНрдп рдХрд╛рд░реНрдп:

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 рдХреЗрд╡рд▓ рдкрд┐рдЫрд▓реА рд╕реНрдерд┐рддрд┐ рдореЗрдВ рд▓реМрдЯрдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рддрд░реНрдХ рдкрд╛рд░рд┐рдд рдХрд░рдиреЗ рдХрд╛ рдЕрд╡рд╕рд░ рдирд╣реАрдВ рджреЗрддрд╛ рд╣реИред

рдореБрдЭреЗ рдХрдВрдЯ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд╣рд╛рдБ рдХрд░рдирд╛ рдЪрд╛рд╣рд┐рдП?


рдПрдХреНрд╕рдЯреЗрдВрд╢рди рдХреА рдорджрдж рд╕реЗ, рдЖрдк рд▓рдЪреАрд▓реЗ рдврдВрдЧ рд╕реЗ рдкреНрд░реЛрдЧреНрд░рд╛рдо рдХреА рдкреНрд░рдЧрддрд┐ рдХреЛ рдирд┐рдпрдВрддреНрд░рд┐рдд рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ, рдЗрд╕рдХреЗ рдкреВрд░рд╛ рд╣реЛрдиреЗ рд╕реЗ рдкрд╣рд▓реЗ рдлрд╝рдВрдХреНрд╢рди рд╕реЗ рд╡рд╛рдкрд╕ рдЖ рд╕рдХрддреЗ рд╣реИрдВ рдФрд░ рдПрдХ рдЕрдкрд╡рд╛рдж рдкреНрд░рдгрд╛рд▓реА рдмрдирд╛ рд╕рдХрддреЗ рд╣реИрдВред
рдХрд┐рд╕реА рдЕрдиреНрдп рд╕рдордп рдкрд░ рдЗрд╕реЗ рд╡рд╛рдкрд╕ рдХрд░рдХреЗ рдЧрдгрдирд╛ рдХреЛ "рдирд┐рд▓рдВрдмрд┐рдд" рдХрд░рдирд╛ рднреА рд╕рдВрднрд╡ рд╣реИ (рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рд╣рдЧреНрд╕ рд╕рдВрдЧрд╛рдорд┐рддрд┐ рдХреЛ рд▓рд╛рдЧреВ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдирд┐рд░рдВрддрд░рддрд╛ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддрд╛ рд╣реИ)ред

рдореВрд▓ рд░реВрдк рд╕реЗ, рдХреЙрдирдЯ рдХрд╛ рдЙрдкрдпреЛрдЧ рдЕрдиреНрдп рд╕рд╛рдзреБрдУрдВ рдХреЗ рд╕рд╛рде рдПрдХ рдЯреНрд░рд╛рдВрд╕рдлрд╛рд░реНрдорд░ рдХреА рддрд░рд╣ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред рдЗрд╕рд╕реЗ рдЬрдЯрд┐рд▓ рдирд┐рдпрдВрддреНрд░рдг рд╕рдВрд░рдЪрдирд╛рдУрдВ рдХреЛ рдмрдирд╛рдиреЗ рдФрд░ / рдпрд╛ рдЧрдгрдирд╛рдУрдВ рдХреЛ рддреЗрдЬ рдХрд░рдиреЗ рдореЗрдВ рдЖрд╕рд╛рдиреА рд╣реЛрддреА рд╣реИред

рдкреНрд░рдпреБрдХреНрдд рд╕рд╛рдордЧреНрд░реА рдХреА рд╕реВрдЪреА


рдирд┐рд░рдВрддрд░рддрд╛ рд╢реИрд▓реА
рд╣реЙрдХреЗрд▓ рдореЗрдВ рдЧреЛрдЯреЛ
рд╣рд╛рд╕реНрдХреЗрд▓ рдХрд╛рд░реНрдпрдХреНрд░рдореЛрдВ рдХреЛ рддреЗрдЬ рдФрд░ рдЫреЛрдЯрд╛ рдмрдирд╛рдирд╛

Source: https://habr.com/ru/post/In127040/


All Articles