рддреАрди рдЙрдкрдпреЛрдЧреА рд╕рд╛рдзреБ

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

рд╣рдорд╕реЗ рдкрд╣рд▓реЗ 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' 


рдирд┐рд╖реНрдХрд░реНрд╖




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

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

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


All Articles