рдзреНрдпрд╛рди рджреЗрдВ: рдиреАрдЪреЗ рджрд┐рдП рдЧрдП рдкрд╛рда рдХреЛ рдкрдврд╝рдиреЗ рд╕реЗ рдкрд╣рд▓реЗ, рдЖрдкрдХреЛ рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рдЗрд╕ рдмрд╛рдд рдХрд╛ рдЕрдВрджрд╛рдЬрд╛ рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдП рдХрд┐ рд╕рдиреНрдпрд╛рд╕реА рдХреНрдпрд╛ рд╣реИрдВред рдЕрдЧрд░ рдРрд╕рд╛ рдирд╣реАрдВ рд╣реИ, рддреЛ рдкрд╣рд▓реЗ
рдЗрд╕ рдкреЛрд╕реНрдЯ рдХреЛ рдкрдврд╝реЗрдВ!
рд╣рдорд╕реЗ рдкрд╣рд▓реЗ
half
рдХрд╛рд░реНрдп рд╣реИ:

рдФрд░ рд╣рдо рдЗрд╕реЗ рдХрдИ рдмрд╛рд░ рд▓рд╛рдЧреВ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ:
half . half $ 8 => 2
рд╕рдм рдХреБрдЫ рдЙрдореНрдореАрдж рдХреЗ рдореБрддрд╛рдмрд┐рдХ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИред рд▓реЗрдХрд┐рди рдЕрдм рдЖрдкрдиреЗ рдлреИрд╕рд▓рд╛ рдХрд┐рдпрд╛ рдХрд┐ рдЗрд╕ рд╕рдорд╛рд░реЛрд╣ рдХреЗ рд╕рд╛рде рдХреНрдпрд╛ рд╣реЛ рд░рд╣рд╛ рд╣реИ, рдЗрд╕рдХрд╛ рд▓реЙрдЧ рдЗрди рдХрд░рдирд╛ рдЕрдЪреНрдЫрд╛ рд╣реЛрдЧрд╛:

half x = (x `div` 2, " " ++ (show x) ++ "!")
рдЕрдЪреНрдЫрд╛, рдмрд╣реБрдд рдЕрдЪреНрдЫрд╛ред рд▓реЗрдХрд┐рди рдХреНрдпрд╛ рд╣реЛрдЧрд╛ рдпрджрд┐ рдЖрдк рдЕрдм рдХрдИ рдмрд╛рд░
half
рдЖрд╡реЗрджрди рдХрд░рдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВ?
half . half $ 8
рдпрд╣рд╛рдБ рд╣реИ рдХрд┐ рд╣рдо рдХреНрдпрд╛
рд╣реЛрддрд╛ рджреЗрдЦрдирд╛
рдЪрд╛рд╣рддреЗ рд╣реИрдВ:
Spoiler : рдпрд╣ рд╕реНрд╡рдЪрд╛рд▓рд┐рдд рд░реВрдк рд╕реЗ рдирд╣реАрдВ рд╣реЛрдЧрд╛ред рд╣рдореЗрдВ рдкреЗрди рд╕реЗ рд╕рдм рдХреБрдЫ рдкреЗрдВрдЯ рдХрд░рдирд╛ рд╣реЛрдЧрд╛:
finalValue = (val2, log1 ++ log2) where (val1, log1) = half 8 (val2, log2) = half val1
рдУрд╣! рдпрд╣ рдПрдХ рд▓реИрдХреЛрдирд┐рдХ рдЬреИрд╕рд╛ рдирд╣реАрдВ рд╣реИ
half . half $ 8
рд▓реЗрдХрд┐рди рдХреНрдпрд╛ рд╣реЛрдЧрд╛ рдЕрдЧрд░ рдЖрдкрдХреЗ рдкрд╛рд╕ рдЕрдзрд┐рдХ рдХрд╛рд░реНрдп рд╣реИрдВ рдЬрд┐рдирдХреЗ рдкрд╛рд╕ рд▓реЙрдЧ рд╣реИ? рдпрд╣ рдирд┐рдореНрди рдпреЛрдЬрдирд╛ рдХреЛ рджрд░реНрд╢рд╛рддрд╛ рд╣реИ: рдкреНрд░рддреНрдпреЗрдХ рдлрд╝рдВрдХреНрд╢рди рдХреЗ рд▓рд┐рдП рдЬреЛ рдорд╛рди рдХреЗ рд╕рд╛рде рд▓реЙрдЧ рд▓реМрдЯрд╛рддрд╛ рд╣реИ, рд╣рдо рдЗрди рд▓реЙрдЧ рдХреЛ рд╕рдВрдпреЛрдЬрд┐рдд рдХрд░рдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВред рдпрд╣ рдПрдХ рд╕рд╛рдЗрдб рдЗрдлреЗрдХреНрдЯ рд╣реИ, рдФрд░ рдХреЛрдИ рднреА рд╕рд╛рдЗрдб рдЗрдлреЗрдХреНрдЯреНрд╕ рдХреА рддрд░рд╣ рдордЬрдмреВрдд рдирд╣реАрдВ рд╣реИ!
рдореЛрдирд╛рдб рд▓реЗрдЦрдХ
рд▓реЗрдЦрдХ рдореЛрдирд╛рдж рдПрдХ рд╕рдлреЗрдж рдШреЛрдбрд╝реЗ рдкрд░ рджрд┐рдЦрд╛рдИ рджреЗрддрд╛ рд╣реИрдореЛрдирд╛рдб рд░рд╛рдЗрдЯрд░ рдПрдХ рд╢рд╛рдВрдд рд╡реНрдпрдХреНрддрд┐рддреНрд╡ рд╣реИред рд╡рд╣ рдХрд╣рддреА рд╣реИ, '' рдЪрд┐рдВрддрд╛ рдордд рдХрд░реЛ, рдЖрджрдореА, рдореИрдВ рддреБрдореНрд╣рд╛рд░реЗ рд▓реЙрдЧ рдХреА рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдХрд░рддрд╛ рд╣реВрдБред "рдЕрдкрдиреЗ рд╕рд╛рдл рдХреЛрдб рдкрд░ рд╡рд╛рдкрд╕ рдЬрд╛рдПрдВ рдФрд░ рдЬрд╝реЗрдкреЗрд▓рд┐рди рд╕реЗ рд╕рдмрд╕реЗ рдЕрдзрд┐рдХ рдирд┐рдЪреЛрдбрд╝реЗрдВ!"
рд▓реЗрдЦрдХ рдХреЗ рдкреНрд░рддреНрдпреЗрдХ рдЙрджрд╛рд╣рд░рдг рдореЗрдВ рдПрдХ рд▓реЙрдЧ рдФрд░ рд░рд┐рдЯрд░реНрди рд╡реИрд▓реНрдпреВ рд╣реИ:

data Writer wa = Writer { runWriter :: (a, w) }
рд▓реЗрдЦрдХ рд╣рдореЗрдВ рдЬреИрд╕реЗ рдХреЛрдб рд▓рд┐рдЦрдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИ
half 8 >>= half
рдареАрдХ рд╣реИ, рдпрд╛ рдЖрдк
<=<
рдлрд╝рдВрдХреНрд╢рди рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ, рдЬреЛ рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рднрд┐рдХреНрд╖реБрдУрдВ рдХреЗ рдХрд╛рд░реНрдпреЛрдВ рдХреА рд╕рдВрд░рдЪрдирд╛ рд╣реИ:
half <=< half $ 8
рдЬреЛ
half . half $ 8
рдХрд░реАрдм рд╣реИ
half . half $ 8
half . half $ 8
ред рдХреВрд▓!
рдЖрдк рд▓реЙрдЧ рдХреЛ рдХреБрдЫ рд▓рд┐рдЦрдиреЗ рдХреЗ рд▓рд┐рдП
tell
рд╕рдХрддреЗ рд╣реИрдВред рдФрд░
return
рд░рд╛рдЗрдЯрд░ рдХреЛ рдпрд╣ рдорд╛рди рджреЗрдЧрд╛ред рдпрд╣рд╛рдВ рд╣рдорд╛рд░рд╛ рдЕрдкрдбреЗрдЯ рдХрд┐рдпрд╛ рдЧрдпрд╛
half
рдХрд╛рд░реНрдп рд╣реИ:
half :: Int -> Writer String Int half x = do tell ("I just halved " ++ (show x) ++ "!") return (x `div` 2)
рд╡рд╣
Writer
рд▓реМрдЯрд╛рддреА рд╣реИ:

рдФрд░ рд╣рдо рдЗрд╕рд╕реЗ рдореВрд▓реНрдп рдирд┐рдХрд╛рд▓рдиреЗ рдХреЗ рд▓рд┐рдП
runWriter
рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ:

runWriter $ half 8 => (4, "I just halved 8!")
рд▓реЗрдХрд┐рди рд╕рдмрд╕реЗ рдЕрдЪреНрдЫреА рдмрд╛рдд рдпрд╣ рд╣реИ рдХрд┐ рдЕрдм рд╣рдо
half
рдХреЙрд▓ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рд╢реНрд░реГрдВрдЦрд▓рд╛ рдмрдирд╛ рд╕рдХрддреЗ рд╣реИрдВ
>>=
:
runWriter $ half 8 >>= half => (2, "I just halved 8!I just halved 4!")
рдпрд╣рд╛рдБ рдХреНрдпрд╛ рд╣реЛрддрд╛ рд╣реИ:

рдЬрд╛рджреБрдИ
>>=
рдЬрд╛рдирддрд╛ рд╣реИ рдХрд┐ рджреЛ рд▓реЗрдЦрдХреЛрдВ рдХреЛ рдХреИрд╕реЗ рд╕рдВрдпреЛрдЬрд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рдП, рдЗрд╕рд▓рд┐рдП рд╣рдореЗрдВ рдЕрдкрдиреЗ рджрдо рдкрд░ рдХреЛрдИ рдердХрд╛рдК рдХреЛрдб рд▓рд┐рдЦрдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдирд╣реАрдВ рд╣реИ! рдпрд╣рд╛рдБ рдкреВрд░реА рдкрд░рд┐рднрд╛рд╖рд╛ рд╣реИ
>>=
:

рд╣рдордиреЗ рдкрд╣рд▓реЗ рд╕реНрд╡рдпрдВ рдЙрд╕реА рдЯреЗрдореНрдкрд▓реЗрдЯ рдХреЛрдб рдХреЛ рд▓рд┐рдЦрд╛ рдерд╛, рдФрд░ рдЕрдм
>>=
рдЗрд╕ рдЬрд┐рдореНрдореЗрджрд╛рд░реА рдХреЛ рд▓рд┐рдпрд╛ред рдХреВрд▓! рд╣рдо
return
рдлрд╝рдВрдХреНрд╢рди рдХрд╛ рднреА рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ
return
, рдЬреЛ рдПрдХ рдореВрд▓реНрдп рд▓реЗрддрд╛ рд╣реИ рдФрд░ рдЗрд╕реЗ рдПрдХ рд╕рдирдХ рдореЗрдВ рдбрд╛рд▓рддрд╛ рд╣реИ:

return val = Writer (val, "")
(
рдзреНрдпрд╛рди рджреЗрдВ : рдпрд╣ рдкрд░рд┐рднрд╛рд╖рд╛
рд▓рдЧрднрдЧ рд╕рд╣реА рд╣реИред рджрд░рдЕрд╕рд▓,
Writer
Monoid
рд╣рдореЗрдВ рдХрд┐рд╕реА рднреА
Monoid
рдХреЛ рд▓реЙрдЧ рдХреЗ рд░реВрдк рдореЗрдВ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИ, рдФрд░ рдпрд╣ рд╕рд┐рд░реНрдл рдПрдХ рд▓рд╛рдЗрди рд╣реИред рдореИрдВрдиреЗ рдЗрд╕реЗ рдпрд╣рд╛рдВ рдереЛрдбрд╝рд╛ рд╕рд░рд▓ рдХрд┐рдпрд╛ рд╣реИред)
рд╢реБрдХреНрд░рд┐рдпрд╛ рдореЛрдирд░ рд░рд╛рдЗрдЯрд░!
рдореЛрдирд╛рдж рдкрд╛рдардХ
рдорд╛рди рд▓реАрдЬрд┐рдП рдХрд┐ рдЖрдк рдХреБрдЫ рд╕реЗрдЯрд┐рдВрдЧреНрд╕ рдХреЛ рдХрдИ рдХрд╛рд░реНрдпреЛрдВ рдореЗрдВ рдкрд╛рд╕ рдХрд░рдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВред рдмрд╕ рдореЛрдирд╛рдб рд░реАрдбрд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВ:

рдпрд╣ рдЖрдкрдХреЛ рдкрд░реНрджреЗ рдХреЗ рдкреАрдЫреЗ рдЯреНрд░рд╛рдВрд╕рдорд┐рд╢рди рддрдВрддреНрд░ рдХреЛ рдЫрд┐рдкрд╛рддреЗ рд╣реБрдП, рд╕рднреА рдХрд╛рд░реНрдпреЛрдВ рдХреЗ рд▓рд┐рдП рдЕрдкрдиреЗ рдЕрд░реНрде рдХреЛ рд╡реНрдпрдХреНрдд рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрдЧрд╛ред рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП:
greeter :: Reader String String greeter = do name <- ask return ("hello, " ++ name ++ "!")
greeter
рдХрд░рдиреЗ рд╡рд╛рд▓рд╛ рдореЛрдирд╛рдж рдкрд╛рдардХ рд▓реМрдЯрд╛рддрд╛ рд╣реИ:

рдпрд╣рд╛рдБ рдЙрд╕рдХреА рдкрд░рд┐рднрд╛рд╖рд╛ рд╣реИ:
data Reader ra = Reader { runReader :: r -> a }
рдкрд╛рдардХ рд╣рдореЗрд╢рд╛ рдПрдХ рд░рдХреНрд╖рдХ рд░рд╣рд╛ рд╣реИред рдЧрд╣рд░рд╛ рдШреЛрдбрд╝рд╛ред рд░реАрдбрд░ рдЕрд▓рдЧ рд╣реИ рдХреНрдпреЛрдВрдХрд┐ рдпрд╣ рд╣рдореЗрдВ рдПрдХ рдлрд╝рдВрдХреНрд╢рди рдХреЛ рд╕рдВрд╕рд╛рдзрд┐рдд рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИ, рдЬреЛ рд╡рд┐рдЪрд╛рд░ рдХрд░рддреЗ рд╕рдордп рднреНрд░рдорд┐рдд рд╣реЛрддрд╛ рд╣реИред рд▓реЗрдХрд┐рди рд╣рдо рд╕рднреА рд╕рдордЭрддреЗ рд╣реИрдВ рдХрд┐ рд╣рдо рдЗрд╕ рдлрд╝рдВрдХреНрд╢рди рдХреЛ рдирд┐рдХрд╛рд▓рдиреЗ рдХреЗ рд▓рд┐рдП
runReader
рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ:

рдФрд░ рд╣рдо рдЗрд╕ рдлрдВрдХреНрд╢рди рдореЗрдВ рдХреБрдЫ рдлрдВрдХреНрд╢рди рдкрд╛рд╕ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ, рдЬреЛ рддрдм
greeter
рдореЗрдВ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ:

runReader greeter $ "adit" => "hello, adit!"
рдЗрд╕ рддрд░рд╣, рдЬрдм рдЖрдк
>>=
рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реИрдВ, рддреЛ рдЖрдкрдХреЛ рдПрдХ рд░реАрдбрд░ рд╡рд╛рдкрд╕ рдорд┐рд▓рдирд╛ рдЪрд╛рд╣рд┐рдПред рдЬрдм рдЖрдк рдЗрд╕реЗ рд░рд╛рдЬреНрдп рдкрд╛рд╕ рдХрд░рддреЗ рд╣реИрдВ, рддреЛ рдЗрд╕реЗ рдЗрд╕ рдореЛрдирд╛рдб рдореЗрдВ рдирд┐рд╣рд┐рдд рд╕рднреА рдХрд╛рд░реНрдпреЛрдВ рдореЗрдВ рд╕реНрдерд╛рдирд╛рдВрддрд░рд┐рдд рдХрд░ рджрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛ред

m >>= k = Reader $ \r -> runReader (k (runReader mr)) r
рдкрд╛рдардХ рд╣рдореЗрд╢рд╛ рдХреБрдЫ рдЬрдЯрд┐рд▓ рд░рд╣рд╛ рд╣реИред рдпрд╣ рдЖрдо рддреМрд░ рдкрд░ рдЗрд╕рдХреА рд╕рдмрд╕реЗ рдЕрдЪреНрдЫреА рдЧреБрдгрд╡рддреНрддрд╛ рд╣реИред
return
Reader
рдореЗрдВ рдореВрд▓реНрдп рдбрд╛рд▓рддрд╛ рд╣реИ:

return a = Reader $ \_ -> a
рдФрд░ рдЕрдВрдд рдореЗрдВ, рдЙрд╕ рд░рд╛рдЬреНрдп рд╕реЗ
ask
рдЬреЛ рдЖрдкрдиреЗ рд╡рд╛рдкрд╕ рдХрд┐рдпрд╛ рдерд╛:
ask = Reader $ \x -> x
рдкрд╛рдардХ рдХреЗ рд╕рд╛рде рдЕрдзрд┐рдХ рд╕рдордп рдмрд┐рддрд╛рдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВ? рдкрдВрдХ рд░реЙрдХ рдХреЛ рдХрд╛рдЯреЗрдВ рдФрд░
рдПрдХ рд▓рдВрдмреЗ рдЙрджрд╛рд╣рд░рдг рдкрд░
рдПрдХ рдирдЬрд╝рд░ рдбрд╛рд▓реЗрдВред
рдореЛрдирд╛рдб рд░рд╛рдЬреНрдп
рд╕реНрдЯреЗрдЯ рдореЛрдирд╛рдб рд░реАрдбрд░ рдХреЗ рдЕрдзрд┐рдХ рдкреНрд░рднрд╛рд╡рд╢рд╛рд▓реА рд╕рдмрд╕реЗ рдЕрдЪреНрдЫреЗ рджреЛрд╕реНрдд рд╣реИрдВ:

рдпрд╣ рдмрд┐рд▓реНрдХреБрд▓ рдкрд╛рдардХ рдореЛрдирд╛рдб рдХреЗ рд╕рдорд╛рди рд╣реИ, рд▓реЗрдХрд┐рди рдЗрд╕рдХреА рдорджрдж рд╕реЗ рдЖрдк рди рдХреЗрд╡рд▓ рдкрдврд╝ рд╕рдХрддреЗ рд╣реИрдВ, рдмрд▓реНрдХрд┐ рд▓рд┐рдЦ рднреА рд╕рдХрддреЗ рд╣реИрдВ!
рдпрд╣рд╛рдБ
State
рдХреА рдкрд░рд┐рднрд╛рд╖рд╛ рд╣реИ:
State sa = State { runState :: s -> (a, s) }

рдЖрдк
put
рд╕рд╛рде рд░рд╛рдЬреНрдп рдкреНрд░рд╛рдкреНрдд рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ рдпрд╛ рдЗрд╕реЗ рдмрджрд▓ рд╕рдХрддреЗ рд╣реИрдВред рдпрд╣рд╛рдБ рдПрдХ рдЙрджрд╛рд╣рд░рдг рд╣реИ:
greeter :: State String String greeter = do name <- get put "tintin" return ("hello, " ++ name ++ "!") runState greeter $ "adit" => ("hello, adit!", "tintin")
рдкреНрдпрд╛рд░рд╛! рдпрджрд┐ рдкрд╛рдардХ "рдЖрдк-рдореИрдВ-рдирд╣реАрдВ-рдкрд░рд┐рд╡рд░реНрддрди" рдЪрд░рд┐рддреНрд░ рдХреЗ рд╕рд╛рде рдерд╛, рддреЛ рд░рд╛рдЬреНрдп, рдЗрд╕рдХреЗ рд╡рд┐рдкрд░реАрдд, рд░рд┐рд╢реНрддреЛрдВ рдХреА рддрд▓рд╛рд╢ рдХрд░рддрд╛ рд╣реИ рдФрд░ рдЦреБрдж рдХреЛ рдмрджрд▓рдиреЗ рдХреЗ рд▓рд┐рдП рддреИрдпрд╛рд░ рд╣реИред
State
monad рдХреА рдкрд░рд┐рднрд╛рд╖рд╛ monad
Reader
рдХреА рдкрд░рд┐рднрд╛рд╖рд╛ рдХреЗ рд╕рдорд╛рди рд╣реИ:
return
:

return a = State $ \s -> (a, s)
>>=
:

m >>= k = State $ \s -> let (a, s') = runState ms in runState (ka) s'
рдирд┐рд╖реНрдХрд░реНрд╖

рд▓реЗрдЦрдХред рд░реАрдбрд░ред рд░рд╛рдЬреНрдпред рдЖрдЬ рдЖрдкрдиреЗ рдЕрдкрдиреЗ рд╣рд╛рд╕реНрдХреЗрд▓ рд╢рд╕реНрддреНрд░рд╛рдЧрд╛рд░ рдореЗрдВ рддреАрди рд╢рдХреНрддрд┐рд╢рд╛рд▓реА рд╣рдерд┐рдпрд╛рд░ рдЬреЛрдбрд╝реЗред рдЗрдирдХрд╛ рдмреБрджреНрдзрд┐рдорд╛рдиреА рд╕реЗ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВред
рдЕрдиреБрд╡рд╛рджрдХ рд╕реЗ: рдореИрдВ рдкреАрдПрдо рдХреА рдХрд┐рд╕реА рднреА рдЯрд┐рдкреНрдкрдгреА рдХреЗ рд▓рд┐рдП рдЕрд╕реАрдо рд░реВрдк рд╕реЗ рдЖрднрд╛рд░реА рд░рд╣реВрдВрдЧрд╛ рдЬреЛ рдЗрд╕ рдЕрдиреБрд╡рд╛рдж рдХреА рдЧреБрдгрд╡рддреНрддрд╛ рдХреЛ рдмреЗрд╣рддрд░ рдмрдирд╛рдиреЗ рдореЗрдВ рдорджрдж рдХрд░реЗрдЧрд╛ред