рд▓реЗрдВрд╕ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рд╣рд╛рд╕реНрдХреЗрд▓ рдореЗрдВ рдЕрдирд┐рд╡рд╛рд░реНрдп рд░реВрдк рд╕реЗ рдкреНрд░реЛрдЧреНрд░рд╛рдорд┐рдВрдЧ рдХрд░рдирд╛

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

рд▓реЗрдВрд╕



рд╕реБрд░реБрдЪрд┐рдкреВрд░реНрдг рдХреЛрдб рдХреЗ рд▓рд┐рдП рдЖрдкрдХрд╛ рдЯрд┐рдХрдЯ рд▓реЗрдВрд╕ рд▓рд╛рдЗрдмреНрд░реЗрд░реА рд╣реИред
рдЖрдк рд╣рдореЗрд╢рд╛ рдХреА рддрд░рд╣ рдЕрдкрдиреЗ рдбреЗрдЯрд╛ рдХреЛ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд░рддреЗ рд╣реИрдВ, рдХреЗрд╡рд▓ рдЕрдкрдиреЗ рдлрд╝реАрд▓реНрдб рдирд╛рдореЛрдВ рдХреА рд╢реБрд░реБрдЖрдд рдореЗрдВ рдЕрдВрдбрд░рд╕реНрдХреЛрд░ рдЬреЛрдбрд╝рддреЗ рд╣реИрдВред рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рд╣рдо рдПрдХ рдЦреЗрд▓ рдХреЛ рдЗрд╕ рдкреНрд░рдХрд╛рд░ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ:
 data Game = Game { _score :: Int , _units :: [Unit] , _boss :: Unit } deriving (Show) 

рдкреНрд░рд╛рдгрд┐рдпреЛрдВ рд╕реЗ рднрд░рд╛ (рдпреВрдирд┐рдЯ):
 data Unit = Unit { _health :: Int , _position :: Point } deriving (Show) 

рдЬрд┐рдирдХреЗ рд╕реНрдерд╛рди рдмрд┐рдВрджреБрдУрдВ рд╕реЗ рдирд┐рд░реНрдзрд╛рд░рд┐рдд рд╣реЛрддреЗ рд╣реИрдВ:
 data Point = Point { _x :: Double , _y :: Double } deriving (Show) 

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

рд╣рдо рджреЛ рддрд░реАрдХреЛрдВ рд╕реЗ рд▓реЗрдВрд╕ рдХрд╛ рдирд┐рд░реНрдорд╛рдг рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред рдкрд╣рд▓рд╛ рд╡рд┐рдХрд▓реНрдк Control.Lens lens рд╕реЗ рд╕реБрд╡рд┐рдзрд╛рдЬрдирдХ lens рдлрд╝рдВрдХреНрд╢рди рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдореИрдиреНрдпреБрдЕрд▓ рд░реВрдк рд╕реЗ рд▓реЗрдВрд╕ рдмрдирд╛рдирд╛ рд╣реИред рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рд╣рдо _score рдлрд╝реАрд▓реНрдб рдХреЗ рд▓рд┐рдП score рд▓реЗрдВрд╕ рдХреЛ рдЗрд╕ рдкреНрд░рдХрд╛рд░ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ:
 import Control.Lens score :: Lens' Game Int score = lens _score (\game v -> game { _score = v }) 

Lens рдЬрдЯрд┐рд▓ рдбреЗрдЯрд╛ рдкреНрд░рдХрд╛рд░ рдиреЗрд╡рд┐рдЧреЗрдЯ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рдирдХреНрд╢реЗ рдХреЗ рд░реВрдк рдореЗрдВ рдЯрд╛рдЗрдк рдХрд░рддреЗ рд╣реИрдВред рд╣рдо _score Game рдХреЛ _score рд╕реЗ рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП score рд▓реЗрдВрд╕ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реИрдВред
рдкреНрд░рдХрд╛рд░ рдпрд╣ рджрд░реНрд╢рд╛рддрд╛ рд╣реИ рдХрд┐ рд╣рдореЗрдВ рдХрд╣рд╛рдБ рд╢реБрд░реВ рдХрд░рдирд╛ рдЪрд╛рд╣рд┐рдП рдФрд░ рдХреИрд╕реЗ рд╕рдорд╛рдкреНрдд рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдП: Lens' Game Int рдЕрд░реНрде рд╣реИ рдХрд┐ рд╣рдореЗрдВ Game рд╢реБрд░реВ рдХрд░рдирд╛ рдЪрд╛рд╣рд┐рдП рдФрд░ рдЕрдВрдд рдореЗрдВ (рд╣рдорд╛рд░реЗ рдорд╛рдорд▓реЗ рдореЗрдВ _score рдлрд╝реАрд▓реНрдб рдХреЗ рд▓рд┐рдП) рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдПред рдЗрд╕реА рддрд░рд╣, рд╣рдорд╛рд░реЗ рдЕрдиреНрдп рд▓реЗрдВрд╕ рд╕реНрдкрд╖реНрдЯ рд░реВрдк рд╕реЗ рдЙрдирдХреЗ рдкреНрд░рдХрд╛рд░реЛрдВ рдХреА рд╢реБрд░реБрдЖрдд рдФрд░ рдЕрдВрдд рдмрд┐рдВрджреБрдУрдВ рдХреЛ рджрд░реНрд╢рд╛рддреЗ рд╣реИрдВ:
 units :: Lens' Game [Unit] units = lens _units (\game v -> game { _units = v }) boss :: Lens' Game Unit boss = lens _boss (\game v -> game { _boss = v }) health :: Lens' Unit Int health = lens _health (\unit v -> unit { _health = v }) position :: Lens' Unit Point position = lens _position (\unit v -> unit { _position = v }) x :: Lens' Point Double x = lens _x (\point v -> point { _x = v }) y :: Lens' Point Double y = lens _y (\point v -> point { _y = v }) 

рд╣рд╛рд▓рд╛рдВрдХрд┐, рд╣рдо рдЕрдХреНрд╕рд░ рдЖрд▓рд╕реА рд╣реЛрддреЗ рд╣реИрдВ рдФрд░ рдирд┐рдпрдорд┐рдд рдХреЛрдб рд▓рд┐рдЦрдирд╛ рдирд╣реАрдВ рдЪрд╛рд╣рддреЗ рд╣реИрдВред рдЗрд╕ рдорд╛рдорд▓реЗ рдореЗрдВ, рдЖрдк Template Haskell рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдПрдХ рдЕрд▓рдЧ рд░рд╛рд╕реНрддрд╛ рдЪреБрди рд╕рдХрддреЗ рд╣реИрдВ рддрд╛рдХрд┐ рдпрд╣ рд╣рдорд╛рд░реЗ рд▓рд┐рдП рд▓реЗрдВрд╕ Template Haskell :
 {-# LANGUAGE TemplateHaskell #-} import Control.Lens data Game = Game { _score :: Int , _units :: [Unit] , _boss :: Unit } deriving (Show) data Unit = Unit { _health :: Int , _position :: Point } deriving (Show) data Point = Point { _x :: Double , _y :: Double } deriving (Show) makeLenses ''Game makeLenses ''Unit makeLenses ''Point 

рдмрд╕ рдпрд╛рдж рд░рдЦреЗрдВ, рдкреИрдЯрд░реНрди рд╡рд╛рд▓реЗ рд╣рд╕реЗрд▓ рдбреЗрдЯрд╛ рдкреНрд░рдХрд╛рд░ рдХреА рдШреЛрд╖рдгрд╛ рдХреЗ рдмрд╛рдж makeLenses рд╡рд╛рд▓реЗ рдореЗрдХреНрд▓рд┐рдореНрд╕ рдШреЛрд╖рдгрд╛ рдХреЛ рдЯреНрд░рдореНрдкреЗрдЯ рдХрд░рддрд╛ рд╣реИред

рдкреНрд░рд╛рд░рдВрднрд┐рдХ рдЕрд╡рд╕реНрдерд╛

рдЕрдЧрд▓реА рдЪреАрдЬрд╝ рдЬреЛ рд╣рдореЗрдВ рдХрд░рдиреЗ рдХреА рдЬрд╝рд░реВрд░рдд рд╣реИ рд╡рд╣ рд╣реИ рдЦреЗрд▓ рдХреА рдкреНрд░рд╛рд░рдВрднрд┐рдХ рдЕрд╡рд╕реНрдерд╛ред
initialState :: рдЦреЗрд▓
 initialState :: Game initialState = Game { _score = 0 , _units = [ Unit { _health = 10 , _position = Point { _x = 3.5, _y = 7.0 } } , Unit { _health = 15 , _position = Point { _x = 1.0, _y = 1.0 } } , Unit { _health = 8 , _position = Point { _x = 0.0, _y = 2.1 } } ] , _boss = Unit { _health = 100 , _position = Point { _x = 0.0, _y = 0.0 } } } 

рд╣рдордиреЗ рддреАрди рдирд╛рдпрдХ рдмрдирд╛рдП, рдЬреЛ рдХрд╛рд▓рдХреЛрдард░реА рдорд╛рд▓рд┐рдХ рдХреЗ рдЦрд┐рд▓рд╛рдл рд▓рдбрд╝реЗрдВрдЧреЗред рд▓рдбрд╝рд╛рдИ рд╢реБрд░реВ рдХрд░рддреЗ рд╣реИрдВ!

рдкрд╣рд▓рд╛ рдХрджрдо

рдЕрдм рд╣рдо рдЕрдкрдиреЗ рд▓реЗрдВрд╕ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ! рдЪрд▓реЛ рд╣рдорд╛рд░реЗ рдпреЛрджреНрдзрд╛рдУрдВ рдХреЗ рд▓рд┐рдП рдмреЙрд╕ рдкрд░ рд╣рдорд▓рд╛ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рдлрд╝рдВрдХреНрд╢рди рдмрдирд╛рдПрдВред
 import Control.Monad.Trans.Class import Control.Monad.Trans.State strike :: StateT Game IO () strike = do lift $ putStrLn "*shink*" boss.health -= 10 

strike рдлрд╝рдВрдХреНрд╢рди рдХрдВрд╕реЛрд▓ рдореЗрдВ рд╣рдореЗрдВ рдПрдХ рд╕рдорд╛рди рдзреНрд╡рдирд┐ рдкреНрд░рд┐рдВрдЯ рдХрд░рддрд╛ рд╣реИ, рдлрд┐рд░ рдмреЙрд╕ 10 рд╕реНрд╡рд╛рд╕реНрдереНрдп рдЗрдХрд╛рдЗрдпреЛрдВ рдХреЗ рд╕реНрд╡рд╛рд╕реНрдереНрдп рдХреЛ рдХрдо рдХрд░рддрд╛ рд╣реИред
рд╣рдорд▓реЗ рдХреЗ рдкреНрд░рдХрд╛рд░ рд╣рдореЗрдВ рджрд┐рдЦрд╛рддреЗ рд╣реИрдВ рдХрд┐ рд╣рдо StateT Game IO рд╕рд╛рде рдХрд╛рдо рдХрд░ рд░рд╣реЗ рд╣реИрдВред рдЖрдк рд╕реЛрдЪ рд╕рдХрддреЗ рд╣реИрдВ рдХрд┐ рдпрд╣ рдПрдХ рдРрд╕реА рдПрдореНрдмреЗрдбреЗрдб рднрд╛рд╖рд╛ рд╣реИ, рдЬрд╣рд╛рдВ рд╣рдо рд╕рд╛рдЗрдб рдЗрдлреЗрдХреНрдЯреНрд╕ (рдпрд╛рдиреА IO ) рдХреЗ рд╢реАрд░реНрд╖ рдкрд░ рд╢реБрджреНрдз рдЧреЗрдо рд╕реНрдЯреЗрдЯреНрд╕ (рдпрд╛рдиреА StateT Game ) рдХреА рдПрдХ рдкрд░рдд рдмрдирд╛рддреЗ рд╣реИрдВ рддрд╛рдХрд┐ рд╣рдо рдПрдХ рд╕рд╛рде рд░рд╛рдЬреНрдпреЛрдВ рдХреЛ рдмрджрд▓ рд╕рдХреЗрдВ рдФрд░ рдХрдВрд╕реЛрд▓ рдкрд░ рд▓рдбрд╝рд╛рдИ рд╕реЗ рд╣рдорд╛рд░реЗ рд╕рдмрд╕реЗ рдкреНрдпрд╛рд░реЗ рдкреНрд░рднрд╛рд╡реЛрдВ рдХреЛ рдкреНрд░рд┐рдВрдЯ рдХрд░ рд╕рдХреЗрдВред ред рдЕрдм рд╣рдореЗрдВ рдХреЗрд╡рд▓ рдпрд╣ рдпрд╛рдж рд░рдЦрдирд╛ рдЪрд╛рд╣рд┐рдП рдХрд┐ рдпрджрд┐ рд╣рдо рд╕рд╛рдЗрдб рдЗрдлреЗрдХреНрдЯреНрд╕ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВ, рддреЛ рд╣рдореЗрдВ lift рдлрд╝рдВрдХреНрд╢рди рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдирд╛ рд╣реЛрдЧрд╛ред
рдЖрдЗрдП рдЗрдВрдЯрд░рдкреНрд░реЗрдЯрд░ ( ghci ) рдореЗрдВ рд╣рдорд╛рд░реЗ рдлрд╝рдВрдХреНрд╢рди рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХрд╛ рдкреНрд░рдпрд╛рд╕ рдХрд░реЗрдВред рдРрд╕рд╛ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рд╣рдореЗрдВ рдкреНрд░рд╛рд░рдВрднрд┐рдХ рдЕрд╡рд╕реНрдерд╛ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ:
рдЬрд▓реНтАНрджреА рд╕реЗ рдЖрд░рдВрдн рдХрд░реЗрдВ
 >>> execStateT strike initialState *shink* Game {_score = 0, _units = [Unit {_health = 10, _position = Poin t {_x = 3.5, _y = 7.0}},Unit {_health = 15, _position = Point {_ x = 1.0, _y = 1.0}},Unit {_health = 8, _position = Point {_x = 0 .0, _y = 2.1}}], _boss = Unit {_health = 90, _position = Point { _x = 0.0, _y = 0.0}}} 

execStateT рдлрд╝рдВрдХреНрд╢рди рд╣рдорд╛рд░реЗ рд░рд╛рдЬреНрдп рдХреЛрдб рдФрд░ рд╣рдорд╛рд░реЗ рдкреНрд░рд╛рд░рдВрднрд┐рдХ рд░рд╛рдЬреНрдп рдХреЛ рд▓реЗрддрд╛ рд╣реИ, рдЗрд╕реЗ рд╢реБрд░реВ рдХрд░рддрд╛ рд╣реИ, рдФрд░ рдПрдХ рдирдпрд╛ рд░рд╛рдЬреНрдп рдмрдирд╛рддрд╛ рд╣реИред рджреБрднрд╛рд╖рд┐рдпрд╛ рд╕реНрд╡рдЪрд╛рд▓рд┐рдд рд░реВрдк рд╕реЗ рд╣рдореЗрдВ рд╕реНрдХреНрд░реАрди рдкрд░ рдкреНрд░рджрд░реНрд╢рд┐рдд рдХрд░рддрд╛ рд╣реИ, рдФрд░ рд╣рдо рддреБрд░рдВрдд рдкрд░рд┐рдгрд╛рдо рдХрд╛ рд╡рд┐рд╢реНрд▓реЗрд╖рдг рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред рдкрд░рд┐рдгрд╛рдо рдЧрдбрд╝рдмрдбрд╝ рдерд╛, рд▓реЗрдХрд┐рди рдЕрдЧрд░ рдЖрдк рдЕрдкрдиреА рдЖрдВрдЦ рдХреЛ рдкреНрд░рд╢рд┐рдХреНрд╖рд┐рдд рдХрд░рддреЗ рд╣реИрдВ, рддреЛ рдЖрдк рджреЗрдЦ рд╕рдХрддреЗ рд╣реИрдВ рдХрд┐ рдмреЙрд╕ рдХреЗ рдкрд╛рд╕ рдЕрдм рдХреЗрд╡рд▓ 90 рд╕реНрд╡рд╛рд╕реНрдереНрдп рдмрд┐рдВрджреБ рд╣реИрдВред
рд╣рдо рдЗрд╕реЗ рдФрд░ рдЖрд╕рд╛рдиреА рд╕реЗ рджреЗрдЦ рд╕рдХрддреЗ рд╣реИрдВ рдпрджрд┐ рд╣рдо рдкрд╣рд▓реЗ рдкрд░рд┐рдгрд╛рдореА рдЕрд╡рд╕реНрдерд╛ рдХреЗ рд▓рд┐рдП рдПрдХ рдирдпрд╛ рдЪрд░ рдмрдирд╛рддреЗ рд╣реИрдВред
 >>> newState <- execStateT strike initialState *shink* 

рдФрд░ рдлрд┐рд░ рд╣рдо рдЗрд╕рдореЗрдВ рд╕реЗ рдЖрд╡рд╢реНрдпрдХ рдЬрд╛рдирдХрд╛рд░реА рдирд┐рдХрд╛рд▓реЗрдВрдЧреЗ:
 >>> newState^.boss.health 90 


рд░рдЪрдирд╛



рдирд┐рдореНрди рдХреЛрдб рдмрд╣реБрдд рдЬрд░реВрд░реА рдФрд░ рд╡рд╕реНрддреБ-рдЙрдиреНрдореБрдЦ рдХреЛрдб рдЬреИрд╕рд╛ рджрд┐рдЦрддрд╛ рд╣реИ:
 boss.health -= 10 

рдпрд╣рд╛рдБ рдХреНрдпрд╛ рд╣реЛ рд░рд╣рд╛ рд╣реИ ?? рд╣рд╛рд╕реНрдХреЗрд▓ рдирд┐рд╢реНрдЪрд┐рдд рд░реВрдк рд╕реЗ рдПрдХ рдмрд╣реБ-рдкреНрд░рддрд┐рдорд╛рди рднрд╛рд╖рд╛ рдирд╣реАрдВ рд╣реИ, рд▓реЗрдХрд┐рди рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдмрд╣реБ-рдкреНрд░рддрд┐рдорд╛рди рдХреЛрдб рдореЗрдВ рджрд┐рдЦрд╛рдИ рджреЗрддрд╛ рд╣реИред
рдЕрд╡рд┐рд╢реНрд╡рд╕рдиреАрдп рд░реВрдк рд╕реЗ, рдЗрд╕ рдХреЛрдб рдореЗрдВ рдХреБрдЫ рднреА рднрд╛рд╖рд╛ рдореЗрдВ рдирд┐рд░реНрдорд┐рдд рдПрдХ рд╡рд┐рд╢реЗрд╖рддрд╛ рдирд╣реАрдВ рд╣реИ!

рд░реБрдХреЛ, (.) рдХреНрдпрд╛ рдпрд╣ рдПрдХ рдХрд╛рд░реНрдпрд╛рддреНрдордХ рд░рдЪрдирд╛ рд╣реИ? рд╕рдЪ рдореЗрдВ!
рдпрд╣ рд╡рд╣ рдЬрдЧрд╣ рд╣реИ рдЬрд╣рд╛рдВ рд╕рднреА рд▓реЗрдВрд╕ рдЬрд╛рджреВ рд╣реЛрддрд╛ рд╣реИред рд▓реЗрдВрд╕ рд╕рдмрд╕реЗ рдЖрдо рдХрд╛рд░реНрдп рд╣реИрдВ, рдФрд░ рд╣рдорд╛рд░реЗ рд╕рднреА "рдмрд╣реБ-рдкреНрд░рддрд┐рдорд╛рди" рдХреЛрдб рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдХрд╛рд░реНрдпреЛрдВ рдХреЗ рдорд┐рд╢реНрд░рдг рд╕реЗ рдЕрдзрд┐рдХ рдХреБрдЫ рдирд╣реАрдВ рд╣реИ!

рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ, Lens' ab рдкреНрд░рдХрд╛рд░ рдЙрдЪреНрдЪ-рдХреНрд░рдо рдХреЗ рдХрд╛рд░реНрдпреЛрдВ рдХрд╛ рдПрдХ рдкрд░реНрдпрд╛рдп рд╣реИ:
 type Lens' ab = forall f . (Functor f) => (b -> fb) -> (a -> fa) 

рдЕрдм рдЖрдкрдХреЛ рд╕рдм рдХреБрдЫ рд╕рдордЭрдиреЗ рдХреА рдЬрд░реВрд░рдд рдирд╣реАрдВ рд╣реИред рдмрд╕ рдпрд╛рдж рд░рдЦреЗрдВ рдХрд┐ Lens' ab рдПрдХ рдЙрдЪреНрдЪ рдХреНрд░рдо рдлрд╝рдВрдХреНрд╢рди рд╣реИ рдЬреЛ рдЗрдирдкреБрдЯ рддрд░реНрдХ рдХреЗ рд░реВрдк рдореЗрдВ рдЯрд╛рдЗрдк (b -> fb) рд▓реЗрддрд╛ рд╣реИ рдФрд░ рдкреНрд░рдХрд╛рд░ рдХрд╛ рдПрдХ рдирдпрд╛ рдлрд╝рдВрдХреНрд╢рди (a -> fa) рд▓реМрдЯрд╛рддрд╛ рд╣реИред Functor рдПрдХ рд╕рд┐рджреНрдзрд╛рдВрдд рдХрд╛ рд╣рд┐рд╕реНрд╕рд╛ рд╣реИ рдЬрд┐рд╕реЗ рдЕрдм "рдЬрд╛рджреВ" рдХреЗ рд░реВрдк рдореЗрдВ рджреЗрдЦрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред
рд╕реБрдирд┐рд╢реНрдЪрд┐рдд рдХрд░реЗрдВ рдХрд┐ рдмреЙрд╕ред рд╕реНрд╡рд╛рд╕реНрдереНрдп :: рд▓реЗрдВрд╕ рдЦреЗрд▓ Int
рдЗрд╕ рдЬреНрдЮрд╛рди рдХреЗ рд╕рд╛рде, рдЖрдЗрдП рджреЗрдЦреЗрдВ рдХрд┐ рдЖрдк boss рдФрд░ health рдХрд╛рд░реНрдпреЛрдВ рдХреЗ рдкреНрд░рдХрд╛рд░реЛрдВ рдХрд╛ рд╡рд┐рд╕реНрддрд╛рд░ рдХреИрд╕реЗ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ:
 boss :: Lens' Game Unit --   : boss :: (Functor f) => (Unit -> f Unit) -> (Game -> f Game) health :: Lens' Unit Int --   : health :: (Functor f) => (Int -> f Int) -> (Unit -> f Unit) 

рдЕрдм рджреЗрдЦрддреЗ рд╣реИрдВ рдХрд╛рд░реНрдпрд╛рддреНрдордХ рд░рдЪрдирд╛ рдХреА рдкрд░рд┐рднрд╛рд╖рд╛:
 (.) :: (b -> c) -> (a -> b) -> (a -> c) (f . g) x = f (gx) 

рдзреНрдпрд╛рди рджреЗрдВ рдХрд┐ рдХреНрдпрд╛ рд╣рдо рдЕрдкрдиреЗ рдЯрд╛рдЗрдк рд╡реЗрд░рд┐рдПрдмрд▓реНрд╕ рдХреА рдЬрдЧрд╣ рд▓реЗрддреЗ рд╣реИрдВ:
 a ~ (Int -> f Int) b ~ (Unit -> f Unit) c ~ (Game -> f Game) 

рддрдм рд╣рдореЗрдВ рджреЛ рд▓реЗрдВрд╕реЛрдВ рдХреА рд╕рдВрд░рдЪрдирд╛ рдХреЗ рд▓рд┐рдП рдПрдХ рдкреВрд░реА рддрд░рд╣ рд╕реЗ рдЕрджреНрд╡рд┐рддреАрдп рдкрддреНрд░рд╛рдЪрд╛рд░ рдорд┐рд▓рддрд╛ рд╣реИ:
 (.) :: ((Unit -> f Unit) -> (Game -> f Game)) -> ((Int -> f Int ) -> (Unit -> f Unit)) -> ((Int -> f Int ) -> (Game -> f Game)) 

рдпрджрд┐ рд╣рдо Lens' рдХреЗ рдкрд░реНрдпрд╛рдпрд╡рд╛рдЪреА рд╢рдмреНрдж рдХреЛ рдЙрд▓рдЯ рджреЗрддреЗ рд╣реИрдВ, рддреЛ рд╣рдореЗрдВ рдпрд╣ рдорд┐рд▓рддрд╛ рд╣реИ:
 (.) :: Lens' Game Unit -> Lens' Unit Int -> Lens' Game Int boss . health :: Lens' Game Int 

рдпрд╣ рдЗрд╕ рдкреНрд░рдХрд╛рд░ рд╣реИ рдХрд┐ рд▓реЗрдВрд╕ рдХреА рд╕рдВрд░рдЪрдирд╛ рднреА рдПрдХ рд▓реЗрдВрд╕ рд╣реИ! рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ, рд▓реЗрдВрд╕ рдПрдХ рд╢реНрд░реЗрдгреА рдмрдирд╛рддреЗ рд╣реИрдВ, рдЬрд╣рд╛рдВ (.) рд╢реНрд░реЗрдгреАрдмрджреНрдз рд░рдЪрдирд╛ рдСрдкрд░реЗрдЯрд░ рд╣реИ, рдФрд░ рдкрд╣рдЪрд╛рди рдлрд╝рдВрдХреНрд╢рди id рднреА рдПрдХ рд▓реЗрдВрд╕ рд╣реИ:
 (.) :: Lens' xy -> Lens' yz -> Lens' xz id :: Lens' xx 

рдирддреАрдЬрддрди, рдЗрд╕ рддрдереНрдп рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реБрдП рдХрд┐ рдЖрдк рдСрдкрд░реЗрдЯрд░ рдХреЗ рдкрд╛рд╕ рд░рд┐рдХреНрдд рд╕реНрдерд╛рди рдирд┐рдХрд╛рд▓ рд╕рдХрддреЗ рд╣реИрдВ, рд╣рдореЗрдВ рдПрдХ рдХреЛрдб рдорд┐рд▓рддрд╛ рд╣реИ рдЬреЛ рдСрдмреНрдЬреЗрдХреНрдЯ-рдУрд░рд┐рдПрдВрдЯреЗрдб рдХреЛрдб рдХреЗ рдЕрдВрдХрди рдХреА рддрд░рд╣ рджрд┐рдЦрддрд╛ рд╣реИ!

рд╢реНрд░реЗрдгрд┐рдпрд╛рдБ рдЙрдбрд╝рдиреЗ рдкрд░ рд╕рдореВрд╣ рдШрдЯрдХреЛрдВ рдХреЛ рдЬреЛрдбрд╝рдиреЗ рдФрд░ рдЕрд╡рд┐рд╢реНрд╡рд╕рдиреАрдп рд░реВрдк рд╕реЗ рдЖрд╕рд╛рди рдмрдирд╛рддреА рд╣реИрдВред рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдпрджрд┐ рд╣рдо рдмреЙрд╕ рдХреЗ рд╕реНрд╡рд╛рд╕реНрдереНрдп рдореЗрдВ рдмрд╛рд░-рдмрд╛рд░ рдмрджрд▓рд╛рд╡ рдХреА рдЙрдореНрдореАрдж рдХрд░рддреЗ рд╣реИрдВ, рддреЛ рд╣рдо рд▓реЗрдВрд╕ рдХреА рд╕рдВрд░рдЪрдирд╛ рдирд┐рд░реНрдзрд╛рд░рд┐рдд рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ:
 bossHP :: Lens' Game Int bossHP = boss.health 

рдФрд░ рдЕрдм рд╣рдо рдЗрд╕рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ рдЬрд╣рд╛рдБ рднреА boss.health ред
 strike :: StateT Game IO () strike = do lift $ putStrLn "*shink*" bossHP -= 10 

рдФрд░ рд╕реНрд╡рд╛рд╕реНрдереНрдп рдХрд╛ рдПрдХ рдирдпрд╛ рдЕрд░реНрде рднреА рдЦреЛрдЬреЗрдВ:
 >>> newState^.bossHP 90 


Perecheslimye

рд▓реЗрдВрд╕ рдПрдХ рдмрд╣реБрдд рд╣реА рд╕реБрдВрджрд░ рд╕рд┐рджреНрдзрд╛рдВрдд рдкрд░ рдЖрдзрд╛рд░рд┐рдд рд╣реИрдВ, рдФрд░ рдЗрд╕рдХреЗ рдкрд░рд┐рдгрд╛рдорд╕реНрд╡рд░реВрдк рд╣рдореЗрдВ рд╡рд╣ рдорд┐рд▓рддрд╛ рд╣реИ рдЬреЛ рд╕рдмрд╕реЗ рдЕрдзрд┐рдХ рдЕрдирд┐рд╡рд╛рд░реНрдп рднрд╛рд╖рд╛рдПрдВ рдмрд╕ рдирд╣реАрдВ рдХрд░ рд╕рдХрддреА рд╣реИрдВ!

рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдорд╛рди рд▓реЗрдВ рдХрд┐ рд╣рдорд╛рд░рд╛ рдорд╛рд▓рд┐рдХ рдПрдХ рдЕрдЬрдЧрд░ рд╣реИ рдЬреЛ рдирд╛рдпрдХреЛрдВ рдХреЛ рдиреБрдХрд╕рд╛рди рдкрд╣реБрдВрдЪрд╛рдиреЗ рд╡рд╛рд▓реА рдЖрдЧ рдореЗрдВ рд╕рд╛рдВрд╕ рд▓реЗрддрд╛ рд╣реИред рд▓реЗрдВрд╕ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ, рд╣рдо рдЗрд╕ рдкреНрд░рднрд╛рд╡ рдХреЛ рдПрдХ рдкрдВрдХреНрддрд┐ рдореЗрдВ рдкреНрд░рд╛рдкреНрдд рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ:
 fireBreath :: StateT Game IO () fireBreath = do lift $ putStrLn "*rawr*" units.traversed.health -= 3 

рдпрд╣ рд▓реЗрдВрд╕ рдХреЗ рд╕рд╛рде рдирдП рддрд░реАрдХреЗ рд╕реЗ рдХрд╛рдо рдХрд░рдирд╛ рд╕рдВрднрд╡ рдмрдирд╛рддрд╛ рд╣реИ!
 traversed :: Traversal' [a] a 

traversed рд╣рдореЗрдВ рд╕реВрдЪреА рдореЗрдВ рдорд╛рдиреЛрдВ рдХреЗ "рдиреАрдЪреЗ рд╕реЗ рдКрдкрд░" рддрдХ рдкрд╣реБрдВрдЪрдиреЗ рдореЗрдВ рдорджрдж рдХрд░рддрд╛ рд╣реИ рддрд╛рдХрд┐ рд╣рдо рдкреВрд░реА рд╕реВрдЪреА рдХреЛ рдореИрдиреНрдпреБрдЕрд▓ рд░реВрдк рд╕реЗ рдЯреНрд░реИрд╡рд░реНрд╕ рдХрд░рдиреЗ рдХреЗ рдмрдЬрд╛рдп рдЗрд╕рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░ рд╕рдХреЗрдВред рд╣рд╛рд▓рд╛рдБрдХрд┐, рдЗрд╕ рдмрд╛рд░ рд╣рдо Traversal' рдкреНрд░рдХрд╛рд░ рдХрд╛ рдЙрдкрдпреЛрдЧ Traversal' Lens' рдмрдЬрд╛рдп Lens' ред

Traversal' рдПрдХ рд╣реА Lens' , рдХреЗрд╡рд▓ рдХрдордЬреЛрд░:
 type Traversal' ab = forall f . (Applicative f) => (b -> fb) -> (a -> fa) 

рдпрджрд┐ рд╣рдо Traversal' рдФрд░ Lens' рдХреА рд░рдЪрдирд╛ рдХрд░рддреЗ рд╣реИрдВ, рддреЛ рд╣рдореЗрдВ рдПрдХ рдХрдордЬреЛрд░ рдкреНрд░рдХрд╛рд░ рдорд┐рд▓рддрд╛ рд╣реИ, рдЬрд┐рд╕рдХрд╛ рдирд╛рдо Traversal' ред рдпрд╣ рдЙрд╕ рдЖрджреЗрд╢ рдХреА рдкрд░рд╡рд╛рд╣ рдХрд┐рдП рдмрд┐рдирд╛ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИ рдЬрд┐рд╕рдореЗрдВ рд╣рдо рдЧрдардмрдВрдзрди рдХрд░рддреЗ рд╣реИрдВ:
 (.) :: Lens' ab -> Traversal' bc -> Traversal' ac (.) :: Traversal' ab -> Lens' bc -> Traversal' ac units :: Lens' Game [Unit] units.traversed :: Traversal' Game Unit units.traversed.health :: Traversal' Game Int 

рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ, рд╣рдореЗрдВ рдпрд╣ рдЬрд╛рдирдиреЗ рдХреА рднреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдирд╣реАрдВ рд╣реИред рдХрдВрдкрд╛рдЗрд▓рд░ рд╕рд╣реА рдкреНрд░рдХрд╛рд░ рд╕реЗ рд╕реНрд╡рдпрдВ рдкрддрд╛ рд▓рдЧрд╛рдПрдЧрд╛:
 >>> :t units.traversed.health units.traversed.health :: Applicative f => (Int -> f Int) -> Game -> f Game 

рдпрд╣ Traversal' Game Int рдХреА рдкрд░рд┐рднрд╛рд╖рд╛ рд╕реЗ рдмрд┐рд▓реНрдХреБрд▓ рдореЗрд▓ рдЦрд╛рддрд╛ рд╣реИ!

рджрд░рдЕрд╕рд▓, рд╣рдо рдЗрди рджреЛрдиреЛрдВ рд▓реЗрдВрд╕реЛрдВ рдХреЛ рдПрдХ рдореЗрдВ рдХреНрдпреЛрдВ рдирд╣реАрдВ рдорд┐рд▓рд╛рддреЗ рд╣реИрдВ?
 partyHP :: Traversal' Game Int partyHP = units.traversed.health fireBreath :: StateT Game IO () fireBreath = do lift $ putStrLn "*rawr*" partyHP -= 3 

рдЖрдЗрдП рд╕реНрд╡рд╛рд╕реНрдереНрдп рдХреЗ рдирдП рдЕрд░реНрде рдХрд╛ рдкрддрд╛ рд▓рдЧрд╛рдиреЗ рдХреЗ рд▓рд┐рдП partyHP рдлрд╝рдВрдХреНрд╢рди рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВ:
 >>> newState <- execStateT fireBreath initialState *rawr* >>> newState^.partyHP <interactive>:3:11: No instance for (Data.Monoid.Monoid Int) arising from a use of `partyHP' ......... 

рдКрдкреНрд╕! рдпрд╣ рдПрдХ рдкреНрд░рдХрд╛рд░ рдХреА рдЧрд▓рддреА рд╣реИ, рдХреНрдпреЛрдВрдХрд┐ рд╣рдореЗрдВ рд╕реНрд╡рд╛рд╕реНрдереНрдп рдХрд╛ рдПрдХрдорд╛рддреНрд░ рдореВрд▓реНрдп рдирд╣реАрдВ рдорд┐рд▓ рд╕рдХрддрд╛ рд╣реИ! рдпрд╣реА рдХрд╛рд░рдг рд╣реИ рдХрд┐ Traversal' Lens' рддреБрд▓рдирд╛ рдореЗрдВ рдХрдордЬреЛрд░ Lens' : рдмрд╛рдпрдкрд╛рд╕ рдХрдИ рдореВрд▓реНрдпреЛрдВ рдХреЛ рдЗрдВрдЧрд┐рдд рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ, рдЗрд╕рд▓рд┐рдП рд╡реЗ рдПрдХрд▓ рдореВрд▓реНрдп рджрд┐рдЦрд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рдЕрдЪреНрдЫреА рддрд░рд╣ рд╕реЗ рдкрд░рд┐рднрд╛рд╖рд┐рдд рддрд░реАрдХреЗ рдХрд╛ рд╕рдорд░реНрдерди рдирд╣реАрдВ рдХрд░рддреЗ рд╣реИрдВред рд╕рд┐рд╕реНрдЯрдо рдиреЗ рд╣рдореЗрдВ рдПрдХ рд╕рдВрднрд╛рд╡рд┐рдд рдмрдЧ рд╕реЗ рдЫреБрдЯрдХрд╛рд░рд╛ рдкрд╛рдиреЗ рдореЗрдВ рдорджрдж рдХреАред

рдЗрд╕рдХреЗ рдмрдЬрд╛рдп, рд╣рдореЗрдВ рдпрд╣ рдирд┐рд░реНрдзрд╛рд░рд┐рдд рдХрд░рдирд╛ рдЪрд╛рд╣рд┐рдП рдХрд┐ рд╣рдо рд╕реВрдЪреА рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рд╕реВрдЪреА рдкреНрд░рд╛рдкреНрдд рдХрд░рдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВ:
 toListOf :: Traversal' ab -> a -> [b] 

рдпрд╣ рд╣рдореЗрдВ рдПрдХ рд╕рдВрддреЛрд╖рдЬрдирдХ рдкрд░рд┐рдгрд╛рдо рджреЗрддрд╛ рд╣реИ:
 >>> toListOf partyHP newState [7,12,5] 

рдпрд╛ toListOf рдлрд╝рдВрдХреНрд╢рди рдХреЗ рдмрд░рд╛рдмрд░ toListOf : (^..) :
 >>> initialState^..partyHP [10,15,8] >>> newState^..partyHP [7,12,5] 

рдЗрд╕рд╕реЗ рд╣рдореЗрдВ рдпрд╣ рд╕реНрдкрд╖реНрдЯ рд░реВрдк рд╕реЗ рдкрддрд╛ рдЪрд▓рддрд╛ рд╣реИ рдХрд┐ рд╣рдореЗрдВ рд╡рд╣ рдЪреАрдЬ рдорд┐рд▓реА рдЬреЛ рд╣рдо fireBreath рд╕рд╛рде рдЪрд╛рд╣рддреЗ рдереЗред

рдФрд░ рдЪрд▓реЛ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдХреБрдЫ рдлреИрдВрд╕реА рдорд┐рд▓рддрд╛ рд╣реИред рд╣рдо рднреМрдЧреЛрд▓рд┐рдХ рдХреНрд╖реЗрддреНрд░ рджреНрд╡рд╛рд░рд╛ рд╕реВрдЪреА рдирд┐рд░реНрдзрд╛рд░рдг рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред рдХреНрдпрд╛ рд╣рдо рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ?
 around :: Point -> Double -> Traversal' Unit Unit around center radius = filtered (\unit -> (unit^.position.x - center^.x)^2 + (unit^.position.y - center^.y)^2 < radius^2 ) 

рдмреЗрд╢рдХ рд╣рдо рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ! рд╣рдо рд╕рд░реНрдХрд▓ рдореЗрдВ рдЖрдЧ рдХреА рд╕рд╛рдВрд╕ рдХреЛ рд╕реАрдорд┐рдд рдХрд░рдиреЗ рдореЗрдВ рд╕рдХреНрд╖рдо рдереЗ!
filtered рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рд╕реИрджреНрдзрд╛рдВрддрд┐рдХ рд░реВрдк рд╕реЗ рдЧрдгрдирд╛ рдпреЛрдЧреНрдп рдирд╣реАрдВ рд╣реИ рдХреНрдпреЛрдВрдХрд┐ рдпрд╣ рддрддреНрд╡реЛрдВ рдХреА рд╕рдВрдЦреНрдпрд╛ рдХреЛ рд╕рдВрдЧреНрд░рд╣реАрдд рдирд╣реАрдВ рдХрд░рддрд╛ рд╣реИ
 fireBreath :: Point -> StateT Game IO () fireBreath target = do lift $ putStrLn "*rawr*" units.traversed.(around target 1.0).health -= 3 

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

рдХрд┐рд╕реА рднреА рдорд╛рдорд▓реЗ рдореЗрдВ, рдЪрд▓реЛ рдЖрдЧ рдмреБрдЭрд╛рдиреЗ рдХреА рдХрд▓ рдкрд░ рд╡рд╛рдкрд╕ рдЬрд╛рдПрдВред рдкрд╣рд▓реЗ, рдЖрдЗрдП рджреЗрдЦреЗрдВ рдХрд┐ рдЙрд╕рдХреЗ рдмрд╛рдж рдХреМрди рд╣реИ:
 > initialState^..units.traversed.position [Point {_x = 3.5, _y = 7.0},Point {_x = 1.0, _y = 1.0},Point {_x = 0.0, _y = 2.1}] 

рд╣рдореНрдо, рджреЛ рдпреЛрджреНрдзрд╛ рдПрдХ-рджреВрд╕рд░реЗ рдХреЗ рдХрд░реАрдм рд╣реИрдВред рдЪрд▓реЛ рд╡рд╣рд╛рдБ рдПрдХ рдЖрдЧ рдХрд╛ рдЧреЛрд▓рд╛ рдлреЗрдВрдХ
 >>> newState <- execStateT (fireBreath (Point 0.5 1.5)) initialState *rawr* >>> (initialState^..partyHP, newState^..partyHP) ([10,15,8],[10,12,5]) 

рд╕рдордЭ рдЧрдпрд╛!

рд╕реНрдХреЗрд▓рд┐рдВрдЧ



рд╣рдо рд▓реЗрдВрд╕ рдХреЗ рд╕рд╛рде рдФрд░ рдЕрдзрд┐рдХ рдЕрдиреЛрдЦреА рдЪреАрдЬреЗрдВ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рд╣рдорд╛рд░реЗ рд╡реИрд╢реНрд╡рд┐рдХ рд░рд╛рдЬреНрдп рдХреЗ рдПрдХ рд╕рдмрд╕реЗрдЯ рдХреЛ рдорд╛рдкрдиреЗ рдХреЗ рд▓рд┐рдПред
 retreat :: StateT Game IO () retreat = do lift $ putStrLn "Retreat!" zoom (units.traversed.position) $ do x += 10 y += 10 

рдкрд╣рд▓реЗ рдХреА рддрд░рд╣, рд╣рдо рджреЛ рд▓реЗрдВрд╕реЛрдВ рдХреЛ рдПрдХ рдореЗрдВ рдЬреЛрдбрд╝ рд╕рдХрддреЗ рд╣реИрдВ рдпрджрд┐ рд╣рдо рдЕрднреА рднреА рдЙрдирдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдЬрд╛ рд░рд╣реЗ рд╣реИрдВ:
 partyLoc :: Traversal' Game Point partyLoc = units.traversed.position retreat :: StateT Game IO () retreat = do lift $ putStrLn "Retreat!" zoom partyLoc $ do x += 10 y += 10 

рдЕрдЪреНрдЫрд╛, рдЪрд▓реЛ рдХреЛрд╢рд┐рд╢ рдХрд░рддреЗ рд╣реИрдВ!
 >>> initialState^..partyLoc [Point {_x = 3.5, _y = 7.0},Point {_x = 1.0, _y = 1.0},Point {_x = 0.0, _y = 2.1}] >>> newState <- execStateT retreat initialState Retreat! >>> newState^..partyLoc [Point {_x = 13.5, _y = 17.0},Point {_x = 11.0, _y = 11.0},Point {_x = 10.0, _y = 12.1}] 

рдЖрдЗрдП рд╣рдорд╛рд░реЗ рд╕рдВрджрд░реНрдн рдореЗрдВ рд╕реНрдХреЗрд▓рд┐рдВрдЧ рдХреЗ рдкреНрд░рдХрд╛рд░ рдХреЛ рдХрд░реАрдм рд╕реЗ рджреЗрдЦреЗрдВ:
 zoom :: Traversal ab -> StateT b IO r -> StateT a IO r 

zoom рдлрд╝рдВрдХреНрд╢рди рдореЗрдВ рдХреБрдЫ рдорд╣рд╛рди рд╕реИрджреНрдзрд╛рдВрддрд┐рдХ рд╕рдВрднрд╛рд╡рдирд╛рдПрдВ рд╣реИрдВред рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рд╣рдо рдЙрдореНрдореАрдж рдХрд░рддреЗ рд╣реИрдВ рдХрд┐ рд╕реНрдХреЗрд▓ рдХрд┐рдП рдЧрдП 2x рд▓реЗрдВрд╕ рдХреА рд╕рдВрд░рдЪрдирд╛ рдХреЛ рдЙрдирдХреА рд░рдЪрдирд╛рдУрдВ рдХреЗ рд╕реНрдХреЗрд▓рд┐рдВрдЧ рдХреЗ рд╕рдорд╛рди рдкрд░рд┐рдгрд╛рдо рджреЗрдирд╛ рдЪрд╛рд╣рд┐рдПред
 zoom lens1 . zoom lens2 = zoom (lens1 . lens2) 

рдФрд░ рд╡рд╣ рдЦрд╛рд▓реА рд▓реЗрдВрд╕ рдЦреБрдж рдХреЛ рд╕реНрдХреЗрд▓рд┐рдВрдЧ рджреЗрдЧрд╛:
 zoom id = id 

рджреВрд╕рд░реЗ рд╢рдмреНрджреЛрдВ рдореЗрдВ, zoom рдлрд╝рдВрдХреНрд╢рди рдПрдХ рдлрд╝рдирдХрд╛рд░ рд╣реИ, рдЬрд┐рд╕рдХрд╛ рдЕрд░реНрде рд╣реИ рдХрд┐ рдпрд╣ рдлрд╝рдирдХрд╛рд░ рдХреЗ рдирд┐рдпрдореЛрдВ рдХрд╛ рдкрд╛рд▓рди рдХрд░рддрд╛ рд╣реИ!

рдЯреАрдореЛрдВ рдХрд╛ рд╕рдВрдпреЛрдЬрди

рдЗрд╕рд╕реЗ рдкрд╣рд▓реЗ, рд╣рдо рдПрдХ рд╕рдордп рдореЗрдВ рдПрдХ рдЯреАрдо рдХреЛ рджреЗрдЦрддреЗ рдереЗ, рд▓реЗрдХрд┐рди рдЕрдм рдЕрд╡рдзрд╛рд░рдгрд╛рдУрдВ рдХреЛ рд╕рдВрдпреЛрдЬрд┐рдд рдХрд░рддреЗ рд╣реИрдВ рдФрд░ рдкрд╛рддреНрд░реЛрдВ рдХреЗ рдмреАрдЪ рд▓рдбрд╝рд╛рдИ рдХреЛ рдЕрдирд┐рд╡рд╛рд░реНрдп рд░реВрдк рд╕реЗ рд╕реЗрдЯ рдХрд░рддреЗ рд╣реИрдВ:
 battle :: StateT Game IO () battle = do -- ! forM_ ["Take that!", "and that!", "and that!"] $ \taunt -> do lift $ putStrLn taunt strike --  ! fireBreath (Point 0.5 1.5) replicateM_ 3 $ do --  ! retreat --    zoom (boss.position) $ do x += 10 y += 10 

рдЕрдЪреНрдЫрд╛, рдЪрд▓рд┐рдП!
 >>> execStateT battle initialState Take that! *shink* and that! *shink* and that! *shink* *rawr* Retreat! Retreat! Retreat! Game {_score = 0, _units = [Unit {_health = 10, _position = Poin t {_x = 33.5, _y = 37.0}},Unit {_health = 12, _position = Point {_x = 31.0, _y = 31.0}},Unit {_health = 5, _position = Point {_x = 30.0, _y = 32.1}}], _boss = Unit {_health = 70, _position = P oint {_x = 30.0, _y = 30.0}}} 

рдореБрдЭреЗ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рд▓реЛрдЧ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдордЬрд╛рдХ рдирд╣реАрдВ рдХрд░ рд░рд╣реЗ рд╣реИрдВ рдЬрдм рд╡реЗ рдХрд╣рддреЗ рд╣реИрдВ рдХрд┐ рд╣рд╛рд╕реНрдХреЗрд▓ рд╕рдмрд╕реЗ рдЕрдЪреНрдЫрд╛ рдЕрдирд┐рд╡рд╛рд░реНрдп рднрд╛рд╖рд╛ рд╣реИ!

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


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

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


All Articles