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

рд╕реБрд░реБрдЪрд┐рдкреВрд░реНрдг рдХреЛрдб рдХреЗ рд▓рд┐рдП рдЖрдкрдХрд╛ рдЯрд┐рдХрдЯ рд▓реЗрдВрд╕ рд▓рд╛рдЗрдмреНрд░реЗрд░реА рд╣реИред
рдЖрдк рд╣рдореЗрд╢рд╛ рдХреА рддрд░рд╣ рдЕрдкрдиреЗ рдбреЗрдЯрд╛ рдХреЛ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд░рддреЗ рд╣реИрдВ, рдХреЗрд╡рд▓ рдЕрдкрдиреЗ рдлрд╝реАрд▓реНрдб рдирд╛рдореЛрдВ рдХреА рд╢реБрд░реБрдЖрдд рдореЗрдВ рдЕрдВрдбрд░рд╕реНрдХреЛрд░ рдЬреЛрдбрд╝рддреЗ рд╣реИрдВред рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рд╣рдо рдПрдХ рдЦреЗрд▓ рдХреЛ рдЗрд╕ рдкреНрд░рдХрд╛рд░ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ:
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
рдпрд╣рд╛рдБ рдХреНрдпрд╛ рд╣реЛ рд░рд╣рд╛ рд╣реИ ?? рд╣рд╛рд╕реНрдХреЗрд▓ рдирд┐рд╢реНрдЪрд┐рдд рд░реВрдк рд╕реЗ
рдПрдХ рдмрд╣реБ-рдкреНрд░рддрд┐рдорд╛рди рднрд╛рд╖рд╛ рдирд╣реАрдВ рд╣реИ, рд▓реЗрдХрд┐рди рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдмрд╣реБ-рдкреНрд░рддрд┐рдорд╛рди рдХреЛрдб рдореЗрдВ рджрд┐рдЦрд╛рдИ рджреЗрддрд╛ рд╣реИред
рдЕрд╡рд┐рд╢реНрд╡рд╕рдиреАрдп рд░реВрдк рд╕реЗ, рдЗрд╕ рдХреЛрдб рдореЗрдВ рдХреБрдЫ рднреА рднрд╛рд╖рд╛ рдореЗрдВ рдирд┐рд░реНрдорд┐рдд рдПрдХ рд╡рд┐рд╢реЗрд╖рддрд╛ рдирд╣реАрдВ рд╣реИ!
boss
рдФрд░ health
рд╕рд┐рд░реНрдл рд▓реЗрдВрд╕ рд╣реИрдВ рдЬрд┐рдиреНрд╣реЗрдВ рд╣рдордиреЗ рдКрдкрд░ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд┐рдпрд╛ рд╣реИ(-=)
- рдЗрдиреНрдлрд┐рдХреНрд╕ рдлрд╝рдВрдХреНрд╢рди(.)
- рд╣рд╛рд╕реНрдХрд▓ Prelude
рд╕реЗ рдПрдХ рдХрд╛рд░реНрдпрд╛рддреНрдордХ рд░рдЪрдирд╛!
рд░реБрдХреЛ,
(.)
рдХреНрдпрд╛ рдпрд╣ рдПрдХ рдХрд╛рд░реНрдпрд╛рддреНрдордХ рд░рдЪрдирд╛ рд╣реИ? рд╕рдЪ рдореЗрдВ!
рдпрд╣ рд╡рд╣ рдЬрдЧрд╣ рд╣реИ рдЬрд╣рд╛рдВ рд╕рднреА рд▓реЗрдВрд╕ рдЬрд╛рджреВ рд╣реЛрддрд╛ рд╣реИред рд▓реЗрдВрд╕ рд╕рдмрд╕реЗ рдЖрдо рдХрд╛рд░реНрдп рд╣реИрдВ, рдФрд░ рд╣рдорд╛рд░реЗ рд╕рднреА "рдмрд╣реБ-рдкреНрд░рддрд┐рдорд╛рди" рдХреЛрдб рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдХрд╛рд░реНрдпреЛрдВ рдХреЗ рдорд┐рд╢реНрд░рдг рд╕реЗ рдЕрдзрд┐рдХ рдХреБрдЫ рдирд╣реАрдВ рд╣реИ!
рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ,
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
рдЕрдм рджреЗрдЦрддреЗ рд╣реИрдВ рдХрд╛рд░реНрдпрд╛рддреНрдордХ рд░рдЪрдирд╛ рдХреА рдкрд░рд┐рднрд╛рд╖рд╛:
(.) :: (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
рдЕрдЪреНрдЫрд╛, рдЪрд▓рд┐рдП!
>>> 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
рд▓рд╛рдЗрдмреНрд░реЗрд░реА рдХрд╛ рдкрд░реНрджрд╛ рдЦреЛрд▓рд╛, рдЬрд┐рд╕реЗ рд╣рд╛рд╕реНрдХреЗрд▓ рдЗрдХреЛрд╕рд┐рд╕реНрдЯрдо рдХреЗ рд╢рд╛рд╣реА рдЦрдЬрд╛рдиреЗ рдореЗрдВ рд╕реЗ рдПрдХ рдорд╛рдирд╛ рдЬрд╛рддрд╛ рд╣реИред рдЖрдк рдмрд╣реБрдд рд╣реА рдкрдардиреАрдп рдФрд░ рд╕реБрд░реБрдЪрд┐рдкреВрд░реНрдг рдХреЛрдб рдореЗрдВ рд╢рдХреНрддрд┐рд╢рд╛рд▓реА рдФрд░ рдЬрдЯрд┐рд▓ рдирд┐рд░реНрдорд╛рдгреЛрдВ рдХреЛ рд╕рдВрдкреАрдбрд╝рд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рд╢реБрджреНрдз рдкреНрд░реЛрдЧреНрд░рд╛рдорд┐рдВрдЧ рдХреЗ рд▓рд┐рдП рд▓реЗрдВрд╕ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред рд╣рд╛рд▓рд╛рдБрдХрд┐, рдЖрдк рдЕрднреА рднреА рдЗрд╕ рдЕрджреНрднреБрдд рдкреБрд╕реНрддрдХрд╛рд▓рдп рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдмрд╣реБрдд рдХреБрдЫ рд▓рд┐рдЦ рд╕рдХрддреЗ рд╣реИрдВред