рд╣рд╛рдп, рд╣реИрдмреНрд░ред
рдкрд┐рдЫрд▓реА рдмрд╛рд░, рд╣рдордиреЗ рд╡рд░реНрдгрди рдХрд┐рдпрд╛ Has
рдкреИрдЯрд░реНрди рд╣реИ, рдЙрди рд╕рдорд╕реНрдпрд╛рдУрдВ рдХреЛ рд░реЗрдЦрд╛рдВрдХрд┐рдд рдХрд░рддрд╛ рд╣реИ рдЬреЛ рдЗрд╕реЗ рд╣рд▓ рдХрд░рддреА рд╣реИрдВ, рдФрд░ рдХреБрдЫ рд╡рд┐рд╢рд┐рд╖реНрдЯ рдЙрджрд╛рд╣рд░рдг рд▓рд┐рдЦреЗ:
instance HasDbConfig AppConfig where getDbConfig = dbConfig instance HasWebServerConfig AppConfig where getWebServerConfig = webServerConfig instance HasCronConfig AppConfig where getCronConfig = cronConfig
рдпрд╣ рдЕрдЪреНрдЫрд╛ рд▓рдЧ рд░рд╣рд╛ рд╣реИред рдпрд╣рд╛рдВ рдХреНрдпрд╛ рдореБрд╢реНрдХрд┐рд▓реЗрдВ рдкреИрджрд╛ рд╣реЛ рд╕рдХрддреА рд╣реИрдВ?

рдареАрдХ рд╣реИ, рдЖрдЗрдП рд╡рд┐рдЪрд╛рд░ рдХрд░реЗрдВ рдХрд┐ рд╣рдореЗрдВ рдХрд┐рди рдЕрдиреНрдп рдЙрджрд╛рд╣рд░рдгреЛрдВ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛ рд╕рдХрддреА рд╣реИред рд╕рдмрд╕реЗ рдкрд╣рд▓реЗ, рдЕрдкрдиреЗ рдЖрдк рдореЗрдВ рдПрдХ рд╡рд┐рдиреНрдпрд╛рд╕ рдХреЗ рд╕рд╛рде рдареЛрд╕ рдкреНрд░рдХрд╛рд░ рдЗрди рдЯрд╛рдЗрдкрдХрд╛рд╕реНрдЯ рдХреЗ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди (рддреБрдЪреНрдЫ) рдХреЗ рд▓рд┐рдП рдЕрдЪреНрдЫреЗ рдЙрдореНрдореАрджрд╡рд╛рд░ рд╣реИрдВ, рдЬреЛ рд╣рдореЗрдВ рддреАрди рдФрд░ рдЙрджрд╛рд╣рд░рдг рджреЗрддреЗ рд╣реИрдВ рдЬрд╣рд╛рдВ рдкреНрд░рддреНрдпреЗрдХ рд╡рд┐рдзрд┐ рдХреЛ id
рдорд╛рдзреНрдпрдо рд╕реЗ рд▓рд╛рдЧреВ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП
instance HasDbConfig DbConfig where getDbConfig = id
рд╡реЗ рд╣рдореЗрдВ рдЖрд╕рд╛рдиреА рд╕реЗ рд╡реНрдпрдХреНрддрд┐рдЧрдд рдкрд░реАрдХреНрд╖рдг рдпрд╛ рд╕рд╣рд╛рдпрдХ рдЙрдкрдпреЛрдЧрд┐рддрд╛рдУрдВ рдХреЛ рд▓рд┐рдЦрдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддреЗ рд╣реИрдВ рдЬреЛ рдкреВрд░реЗ AppConfig
рд╕реНрд╡рддрдВрддреНрд░ рд╣реИрдВред
рдпрд╣ рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рдЙрдмрд╛рдК рд╣реИ, рд▓реЗрдХрд┐рди рдЕрднреА рднреА рдЬрд╛рд░реА рд╣реИред рдпрд╣ рдХрд▓реНрдкрдирд╛ рдХрд░рдирд╛ рдЖрд╕рд╛рди рд╣реИ рдХрд┐ рдХреБрдЫ рдПрдХреАрдХрд░рдг рдкрд░реАрдХреНрд╖рдг рдореЙрдбреНрдпреВрд▓ рдХреА рдПрдХ рдЬреЛрдбрд╝реА рдХреА рдмрд╛рддрдЪреАрдд рдХреА рдЬрд╛рдВрдЪ рдХрд░рддреЗ рд╣реИрдВ, рдФрд░ рд╣рдо рдЕрднреА рднреА рдкреВрд░реЗ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдХреЗ рдХреЙрдиреНрдлрд╝рд┐рдЧрд░реЗрд╢рди рдкрд░ рдирд┐рд░реНрднрд░ рдирд╣реАрдВ рдХрд░рдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВ, рдЗрд╕рд▓рд┐рдП рдЕрдм рд╣рдореЗрдВ рдЫрд╣ рдЙрджрд╛рд╣рд░рдг (рджреЛ рдкреНрд░рдХрд╛рд░ рдкреНрд░рддрд┐) рд▓рд┐рдЦрдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ, рдЬрд┐рдирдореЗрдВ рд╕реЗ рдкреНрд░рддреНрдпреЗрдХ рдХреЛ рдХрдо рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХрдо рдХрд┐рдпрд╛ fst
рдпрд╛ snd
рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, DbConfig
:
instance HasDbConfig (DbConfig, b) where getDbConfig = fst instance HasDbConfig (a, DbConfig) where getDbConfig = snd
рд╣реЙрд░рд░ред рдпрд╣ рдЖрд╢рд╛ рдХреА рдЬрд╛рддреА рд╣реИ рдХрд┐ рд╣рдореЗрдВ рдПрдХ рд╣реА рд╕рдордп рдореЗрдВ рддреАрди рдореЙрдбреНрдпреВрд▓ рдХреЗ рд╕рдВрдЪрд╛рд▓рди рдХрд╛ рдкрд░реАрдХреНрд╖рдг рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдирд╣реАрдВ рд╣реЛрдЧреА - рдЕрдиреНрдпрдерд╛ рдЖрдкрдХреЛ рдиреМ рдЙрдмрд╛рдК рдЙрджрд╛рд╣рд░рдг рд▓рд┐рдЦрдиреЗ рд╣реЛрдВрдЧреЗред рдХрд┐рд╕реА рднреА рдорд╛рдорд▓реЗ рдореЗрдВ, рдореИрдВ рд╡реНрдпрдХреНрддрд┐рдЧрдд рд░реВрдк рд╕реЗ рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рдмрд╣реБрдд рдЕрд╕реБрд╡рд┐рдзрд╛рдЬрдирдХ рд╣реВрдВ, рдФрд░ рдореИрдВ рдЗрд╕ рдорд╛рдорд▓реЗ рдХреЛ рдХреЛрдб рдХреЗ рдПрдХ рджрд░реНрдЬрди рдЕрддрд┐рд░рд┐рдХреНрдд рд▓рд╛рдЗрдиреЗрдВ рд▓рд┐рдЦрдиреЗ рдХреЗ рдмрдЬрд╛рдп рдХреБрдЫ рдШрдВрдЯреЛрдВ рдХреЛ рд╕реНрд╡рдЪрд╛рд▓рд┐рдд рдХрд░рдиреЗ рдореЗрдВ рдХрдИ рдШрдВрдЯреЗ рдмрд┐рддрд╛рдКрдВрдЧрд╛ред
рдпрджрд┐ рдЖрдк рд░реБрдЪрд┐ рд░рдЦрддреЗ рд╣реИрдВ рдХрд┐ рдЗрд╕ рд╕рдорд╕реНрдпрд╛ рдХреЛ рд╕рд╛рдорд╛рдиреНрдп рддрд░реАрдХреЗ рд╕реЗ рдХреИрд╕реЗ рд╣рд▓ рдХрд┐рдпрд╛ рдЬрд╛рдП, рдЗрд╕рдХреЗ рдЕрд▓рд╛рд╡рд╛, рдпрд╣ рдирд┐рд░реНрднрд░ рдкреНрд░рдХрд╛рд░ рд╣реИ, рдФрд░ рдпрд╣ рд╕рдм рдХреИрд╕реЗ рд╣рд╛рд╕реНрдХреЗрд▓ - рд╡реЗрд▓реНрдХрдо рдмрд┐рд▓реНрд▓реА рдХреА рддрд░рд╣ рджрд┐рдЦрд╛рдИ рджреЗрдЧрд╛ред
Has
рдХреНрд▓рд╛рд╕ рдХреЛ рд╕рд╛рд░рд╛рдВрд╢рд┐рдд рдХрд░рдирд╛
рдкрд╣рд▓реЗ, рдзреНрдпрд╛рди рджреЗрдВ рдХрд┐ рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдЕрд▓рдЧ-рдЕрд▓рдЧ рд╡рд╛рддрд╛рд╡рд░рдг рдХреЗ рд▓рд┐рдП рдЕрд▓рдЧ-рдЕрд▓рдЧ рдХрдХреНрд╖рд╛рдПрдВ рд╣реИрдВред рдпрд╣ рдПрдХ рд╕рд╛рд░реНрд╡рднреМрдорд┐рдХ рд╕рдорд╛рдзрд╛рди рдмрдирд╛рдиреЗ рдореЗрдВ рд╣рд╕реНрддрдХреНрд╖реЗрдк рдХрд░ рд╕рдХрддрд╛ рд╣реИ, рдЗрд╕рд▓рд┐рдП рд╣рдордиреЗ рдкрд░реНрдпрд╛рд╡рд░рдг рдХреЛ рдПрдХ рдЕрд▓рдЧ рдкреИрд░рд╛рдореАрдЯрд░ рдореЗрдВ рд░рдЦрд╛ рд╣реИ:
class Has part record where extract :: record -> part
рд╣рдо рдХрд╣ рд╕рдХрддреЗ рд╣реИрдВ рдХрд┐ Has part record
рдорддрд▓рдм рд╣реИ рдХрд┐ рдЯрд╛рдЗрдк record
рдХреЗ рдореВрд▓реНрдп рд╕реЗ рдХреБрдЫ рдкреНрд░рдХрд╛рд░ рдХреЗ part
рдирд┐рдХрд╛рд▓реЗ рдЬрд╛ рд╕рдХрддреЗ рд╣реИрдВред рдЗрди рд╢рдмреНрджреЛрдВ рдореЗрдВ, рд╣рдорд╛рд░реЗ рдЕрдЪреНрдЫреЗ рдкреБрд░рд╛рдиреЗ HasDbConfig
Has DbConfig
рд╣реЛ Has DbConfig
, рдФрд░ рдЗрд╕реА рддрд░рд╣ рдЕрдиреНрдп рдЯрд╛рдЗрдкрдХрд╛рд╕реНрдЯ рдХреЗ рд▓рд┐рдП рдЬреЛ рд╣рдордиреЗ рдкрд╣рд▓реЗ рд▓рд┐рдЦрд╛ рдерд╛ред рдпрд╣ рд▓рдЧрднрдЧ рд╡рд┐рд╢реБрджреНрдз рд░реВрдк рд╕реЗ рд╡рд╛рдХреНрдп-рд╡рд┐рдиреНрдпрд╛рд╕ рдореЗрдВ рдмрджрд▓ рдЬрд╛рддрд╛ рд╣реИ, рдФрд░, рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рд╣рдорд╛рд░реА рдкрд┐рдЫрд▓реА рдкреЛрд╕реНрдЯ рдХреЗ рдХрд╛рд░реНрдпреЛрдВ рдореЗрдВ рд╕реЗ рдПрдХ рдХрд╛ рдкреНрд░рдХрд╛рд░ рдмрджрд▓ рдЬрд╛рддрд╛ рд╣реИ
doSmthWithDbAndCron :: (MonadReader rm, HasDbConfig r, HasCronConfig r) => ...
рдореЗрдВ
doSmthWithDbAndCron :: (MonadReader rm, Has DbConfig r, Has CronConfig r) => ...
рдПрдХрдорд╛рддреНрд░ рдкрд░рд┐рд╡рд░реНрддрди рд╕рд╣реА рд╕реНрдерд╛рдиреЛрдВ рдореЗрдВ рдХреБрдЫ рд╕реНрдерд╛рди рд╣реИред
рдЗрд╕рдХреЗ рдЕрд▓рд╛рд╡рд╛, рд╣рдо рдкреНрд░рдХрд╛рд░ рдХреЗ рдЕрдиреБрдорд╛рди рдореЗрдВ рдмрд╣реБрдд рдХреБрдЫ рдирд╣реАрдВ рдЦреЛрддреЗ рд╣реИрдВ: рдПрдХ рдЯрд╛рдЗрдорд░ рдЕрднреА рднреА рдЕрднреНрдпрд╛рд╕ рдореЗрдВ рд╕рд╛рдордирд╛ рдХрд┐рдП рдЧрдП рдЕрдзрд┐рдХрд╛рдВрд╢ рдорд╛рдорд▓реЛрдВ рдореЗрдВ рдЖрд╕рдкрд╛рд╕ рдХреЗ рд╕рдВрджрд░реНрдн рдореЗрдВ extract
рдХреЗ рдЖрд╡рд╢реНрдпрдХ рд╡рд╛рдкрд╕реА рдореВрд▓реНрдп рдХрд╛ рдЙрддреНрдкрд╛рджрди рдХрд░ рд╕рдХрддрд╛ рд╣реИред
рдЕрдм рдЬрдм рд╣рдо рд╡рд┐рд╢рд┐рд╖реНрдЯ рдкреНрд░рдХрд╛рд░ рдХреЗ рдкрд░реНрдпрд╛рд╡рд░рдг рдХреА рдкрд░рд╡рд╛рд╣ рдирд╣реАрдВ рдХрд░рддреЗ рд╣реИрдВ, рддреЛ рдЖрдЗрдП рджреЗрдЦреЗрдВ рдХрд┐ рдХреМрди рд╕реЗ рд░рд┐рдХреЙрд░реНрдб рдирд┐рд╢реНрдЪрд┐рдд part
рд▓рд┐рдП Has part record
рдХреНрд▓рд╛рд╕ рдХреЛ рд▓рд╛рдЧреВ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред рдЗрд╕ рдХрд╛рд░реНрдп рдХреА рдПрдХ рдЕрдЪреНрдЫреА рдкреНрд░реЗрд░рдХ рд╕рдВрд░рдЪрдирд╛ рд╣реИ:
- рдкреНрд░рддреНрдпреЗрдХ рдкреНрд░рдХрд╛рд░ рдореЗрдВ рд╕реНрд╡рдпрдВ рд╣реЛрддрд╛ рд╣реИ:
Has record record
рдХреЛ рддреБрдЪреНрдЫ рддрд░реАрдХреЗ рд╕реЗ рд▓рд╛рдЧреВ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ ( extract = id
)ред - рдпрджрд┐
record
рдкреНрд░рдХрд╛рд░ rec1
рдФрд░ rec2
рдХрд╛ рдПрдХ рдЙрддреНрдкрд╛рдж рд╣реИ, рддреЛ Has part record
рдХрд╛рд░реНрдпрд╛рдиреНрд╡рд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ рдпрджрд┐ рдФрд░ рдХреЗрд╡рд▓ рдпрд╛ рддреЛ Has part rec1
рдпрд╛ Has part rec2
ред - рдпрджрд┐
record
рдкреНрд░рдХрд╛рд░ rec1
рдФрд░ rec2
рдХрд╛ рдпреЛрдЧ рд╣реИ, рддреЛ Has part record
рдХрд╛рд░реНрдпрд╛рдиреНрд╡рд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ рдпрджрд┐ рдФрд░ рдХреЗрд╡рд▓ Has part rec1
рдФрд░ Has part rec2
ред рдпрджреНрдпрдкрд┐ рдЗрд╕ рд╕рдВрджрд░реНрдн рдореЗрдВ рдЗрд╕ рдорд╛рдорд▓реЗ рдХреА рд╡реНрдпрд╛рд╡рд╣рд╛рд░рд┐рдХ рд╡реНрдпрд╛рдкрдХрддрд╛ рд╕реНрдкрд╖реНрдЯ рдирд╣реАрдВ рд╣реИ, рдлрд┐рд░ рднреА рдпрд╣ рдкреВрд░реНрдгрддрд╛ рдХреЗ рд▓рд┐рдП рдзреНрдпрд╛рди рджреЗрдиреЗ рдпреЛрдЧреНрдп рд╣реИред
рдЗрд╕рд▓рд┐рдП, рдРрд╕рд╛ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рд╣рдордиреЗ рдПрдХ рдПрд▓реНрдЧреЛрд░рд┐рдереНрдо рдХрд╛ рдПрдХ рд╕реНрдХреЗрдЪ рддреИрдпрд╛рд░ рдХрд┐рдпрд╛ рд╣реИ рддрд╛рдХрд┐ рдпрд╣ рдирд┐рд░реНрдзрд╛рд░рд┐рдд рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХреЗ рдХрд┐ Has part record
part
рдФрд░ record
рдбреЗрдЯрд╛ рдХреЗ рд▓рд┐рдП рд▓рд╛рдЧреВ рд╣реИ!
рд╕реМрднрд╛рдЧреНрдп рд╕реЗ, рдкреНрд░рдХрд╛рд░ рдкрд░ рдЗрд╕ рддрд░рд╣ рдХреЗ рдЖрдЧрдордирд╛рддреНрдордХ рддрд░реНрдХ рд╣рд╛рд╕реНрдХреЗрд▓ рдкреАрдврд╝реА рддрдВрддреНрд░ рдкрд░ рдмрд╣реБрдд рдЕрдЪреНрдЫреА рддрд░рд╣ рд╕реЗ рдлрд┐рдЯ рдмреИрдарддрд╛ рд╣реИред рд╕рдВрдХреНрд╖реЗрдк рдореЗрдВ рдФрд░ рд╕рд░рд▓реАрдХрд░рдг, рдЬреЗрдирд░рд┐рдХ рд╣рд╛рд╕реНрдХреЗрд▓ рдореЗрдВ рд╕рд╛рдорд╛рдиреНрдпреАрдХреГрдд рдореЗрдЯрд╛рдкреНрд░реЛрдЧреНрд░рд╛рдорд┐рдВрдЧ рдХреЗ рддрд░реАрдХреЛрдВ рдореЗрдВ рд╕реЗ рдПрдХ рд╣реИ, рдЬрд┐рд╕рдХреЗ рдкрд░рд┐рдгрд╛рдорд╕реНрд╡рд░реВрдк рдЕрд╡рд▓реЛрдХрди рд╣реИ рдХрд┐ рдкреНрд░рддреНрдпреЗрдХ рдкреНрд░рдХрд╛рд░ рдпрд╛ рддреЛ рдПрдХ рдпреЛрдЧ рдкреНрд░рдХрд╛рд░, рдПрдХ рдЙрддреНрдкрд╛рдж рдкреНрд░рдХрд╛рд░, рдпрд╛ рдПрдХ рдХреНрд╖реЗрддреНрд░ рдХреЗ рд╕рд╛рде рдПрдХ рдПрдХрд▓-рдирд┐рд░реНрдорд╛рдг рдореВрд▓ рдкреНрд░рдХрд╛рд░ рд╣реИред
рдореИрдВ рдЬреЗрдиреЗрд░рд┐рдХ рдкрд░ рдПрдХ рдФрд░ рдЯреНрдпреВрдЯреЛрд░рд┐рдпрд▓ рдирд╣реАрдВ рд▓рд┐рдЦреВрдВрдЧрд╛, рдЗрд╕рд▓рд┐рдП рдмрд╕ рдХреЛрдб рдкрд░ рдЬрд╛рдПрдВред
рдкрд╣рд▓рд╛ рдкреНрд░рдпрд╛рд╕
рд╣рдо рд╕рд╣рд╛рдпрдХ рд╢реНрд░реЗрдгреА рдХреЗ GHas
рдорд╛рдзреНрдпрдо рд╕реЗ рдЕрдкрдиреА Generic
рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдХреА рдХреНрд▓рд╛рд╕рд┐рдХ рдкрджреНрдзрддрд┐ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВрдЧреЗ:
class GHas part grecord where gextract :: grecord p -> part
рдпрд╣рд╛рдБ grecord
рд╣рдорд╛рд░реЗ record
рдкреНрд░рдХрд╛рд░ рдХрд╛ рдПрдХ Generic
рдкреНрд░рддрд┐рдирд┐рдзрд┐рддреНрд╡ рд╣реИред
GHas
рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдЙрди рдкреНрд░реЗрд░рдХ рд╕рдВрд░рдЪрдирд╛ рдХрд╛ рдЕрдиреБрд╕рд░рдг рдХрд░рддреЗ рд╣реИрдВ рдЬрд┐рдиреНрд╣реЗрдВ рд╣рдордиреЗ рдКрдкрд░ рдЙрд▓реНрд▓реЗрдЦ рдХрд┐рдпрд╛ рд╣реИ:
instance GHas record (K1 i record) where gextract (K1 x) = x instance GHas part record => GHas part (M1 it record) where gextract (M1 x) = gextract x instance GHas part l => GHas part (l :*: r) where gextract (l :*: _) = gextract l instance GHas part r => GHas part (l :*: r) where gextract (_ :*: r) = gextract r
K1
рдмреЗрд╕ рдХреЗрд╕ рд╕реЗ рдореЗрд▓ рдЦрд╛рддрд╛ рд╣реИредM1
- рдЬреЗрдирд░рд┐рдХ-рд╡рд┐рд╢рд┐рд╖реНрдЯ рдореЗрдЯрд╛рдбреЗрдЯрд╛ рдЬрд┐рд╕реЗ рд╣рдореЗрдВ рдЕрдкрдиреЗ рдХрд╛рд░реНрдп рдореЗрдВ рдЖрд╡рд╢реНрдпрдХрддрд╛ рдирд╣реАрдВ рд╣реИ, рдЗрд╕рд▓рд┐рдП рд╣рдо рдмрд╕ рдЙрдиреНрд╣реЗрдВ рдЕрдирджреЗрдЦрд╛ рдХрд░рддреЗ рд╣реИрдВ рдФрд░ рдЙрдирдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдЬрд╛рддреЗ рд╣реИрдВред- рдЙрддреНрдкрд╛рдж рдкреНрд░рдХрд╛рд░
l :*: r
рд▓рд┐рдП рдкрд╣рд▓рд╛ рдЙрджрд╛рд╣рд░рдг рдЙрд╕ рд╕реНрдерд┐рддрд┐ рд╕реЗ рдореЗрд▓ рдЦрд╛рддрд╛ рд╣реИ рдЬрдм рдЙрддреНрдкрд╛рдж рдХреЗ "рдмрд╛рдПрдВ" рднрд╛рдЧ рдореЗрдВ рдЙрд╕ рдкреНрд░рдХрд╛рд░ рдХреЗ part
рдХрд╛ рдореВрд▓реНрдп рд╣реЛрддрд╛ рд╣реИ рдЬрд┐рд╕рдХреА рд╣рдореЗрдВ рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрддреА рд╣реИ (рд╕рдВрднрд╡рддрдГ, рдкреБрдирд░рд╛рд╡рд░реНрддреА)ред - рдЗрд╕реА рдкреНрд░рдХрд╛рд░, рдЙрддреНрдкрд╛рдж рдкреНрд░рдХрд╛рд░
l :*: r
рд▓рд┐рдП рджреВрд╕рд░рд╛ рдЙрджрд╛рд╣рд░рдг рдЙрд╕ рд╕реНрдерд┐рддрд┐ рд╕реЗ рдореЗрд▓ рдЦрд╛рддрд╛ рд╣реИ рдЬрдм рдЙрддреНрдкрд╛рдж рдХреЗ "рджрд╛рдПрдВ" рднрд╛рдЧ рдореЗрдВ рдЯрд╛рдЗрдк part
(рд╕реНрд╡рд╛рднрд╛рд╡рд┐рдХ рд░реВрдк рд╕реЗ, рд╕рдВрднрд╡рддрдГ, рдкреБрдирд░рд╛рд╡рд░реНрддреА) рдХрд╛ рд╡рд╛рдВрдЫрд┐рдд рдорд╛рди рд╣реЛрддрд╛ рд╣реИред
рд╣рдо рдпрд╣рд╛рдВ рдХреЗрд╡рд▓ рдЙрддреНрдкрд╛рдж рдкреНрд░рдХрд╛рд░реЛрдВ рдХрд╛ рд╕рдорд░реНрдерди рдХрд░рддреЗ рд╣реИрдВред рдореЗрд░реА рд╡реНрдпрдХреНрддрд┐рдкрд░рдХ рдзрд╛рд░рдгрд╛ рдпрд╣ рд╣реИ рдХрд┐ рдорд╛рддреНрд░рд╛рдУрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдЕрдХреНрд╕рд░ MonadReader
рдФрд░ рдЗрд╕реА рддрд░рд╣ рдХреА рдХрдХреНрд╖рд╛рдУрдВ рдХреЗ рд▓рд┐рдП рд╕рдВрджрд░реНрднреЛрдВ рдореЗрдВ рдирд╣реАрдВ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рдЗрд╕рд▓рд┐рдП рдЙрдиреНрд╣реЗрдВ рд╡рд┐рдЪрд╛рд░ рдХреЛ рд╕рд░рд▓ рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдЙрдкреЗрдХреНрд╖рд┐рдд рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред
рдЗрд╕рдХреЗ рдЕрд▓рд╛рд╡рд╛, рдпрд╣ рдзреНрдпрд╛рди рд░рдЦрдирд╛ рдЙрдкрдпреЛрдЧреА рд╣реИ рдХрд┐ рдкреНрд░рддреНрдпреЗрдХ -ary рдкреНрд░рдХрд╛рд░-рдЙрддреНрдкрд╛рдж (a1, ..., an)
рдХреЛ рдПрдХ рд░рдЪрдирд╛ рдХреЗ рд░реВрдк рдореЗрдВ рджрд░реНрд╢рд╛рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ рдЬреЛрдбрд╝реЗ (a1, (a2, (a3, (..., an))))
, рдЗрд╕рд▓рд┐рдП рдореИрдВ рдЦреБрдж рдХреЛ рдЬреЛрдбрд╝реЗ рдХреЗ рд╕рд╛рде рдЙрддреНрдкрд╛рдж рдкреНрд░рдХрд╛рд░реЛрдВ рдХреЛ рдЬреЛрдбрд╝рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реВрдВред
рд╣рдорд╛рд░реЗ GHas
рд╕рд╛рде, рдЖрдк рдЬреЗрдирд░рд┐рдХ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рд╡рд╛рд▓реЗ Has
рд▓рд┐рдП рдПрдХ рдбрд┐рдлрд╝реЙрд▓реНрдЯ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рд▓рд┐рдЦ рд╕рдХрддреЗ рд╣реИрдВ:
class Has part record where extract :: record -> part default extract :: Generic record => record -> part extract = gextract . from
рд╣реЛ рдЧрдпрд╛ред
рдпрд╛ рдирд╣реАрдВ?
рд╕рдорд╕реНрдпрд╛
рдпрджрд┐ рд╣рдо рдЗрд╕ рдХреЛрдб рдХреЛ рд╕рдВрдХрд▓рд┐рдд рдХрд░рдиреЗ рдХрд╛ рдкреНрд░рдпрд╛рд╕ рдХрд░рддреЗ рд╣реИрдВ, рддреЛ рд╣рдо рджреЗрдЦреЗрдВрдЧреЗ рдХрд┐ рдпрд╣ рдбрд┐рдлрд╝реЙрд▓реНрдЯ рд░реВрдк рд╕реЗ рдЗрд╕ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреЗ рдкреНрд░рдпрд╛рд╕ рдХреЗ рдмрд┐рдирд╛ рднреА taypechaetsya рдирд╣реАрдВ рдХрд░рддрд╛ рд╣реИ, рд╡рд╣рд╛рдВ рдХреБрдЫ рдЕрддрд┐рд╡реНрдпрд╛рдкреА рдЙрджрд╛рд╣рд░рдгреЛрдВ рдХреА рд░рд┐рдкреЛрд░реНрдЯрд┐рдВрдЧ рдХрд░рддрд╛ рд╣реИред рдЗрд╕рд╕реЗ рднреА рдмрджрддрд░, рдпреЗ рдЙрджрд╛рд╣рд░рдг рдХреБрдЫ рдорд╛рдпрдиреЛрдВ рдореЗрдВ рд╕рдорд╛рди рд╣реИрдВред рдРрд╕рд╛ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдпрд╣ рдкрддрд╛ рд▓рдЧрд╛рдиреЗ рдХрд╛ рд╕рдордп рд╣реИ рдХрд┐ рд╣рд╛рд╕реНрдХреЗрд▓ рдореЗрдВ рдЙрджрд╛рд╣рд░рдгреЛрдВ рдХреЛ рд╣рд▓ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рддрдВрддреНрд░ рдХреИрд╕реЗ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИред
рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рд╣реЛ рд╕рдХрддрд╛ рд╣реИ
instance context => Foo barPattern bazPattern where ...
(рд╡реИрд╕реЗ, рдЗрд╕ рдЪреАрдЬ рдХреЗ рдмрд╛рдж =>
рдХреЛ рдЙрджрд╛рд╣рд░рдг рдкреНрд░рдзрд╛рди рдХрд╣рд╛ рдЬрд╛рддрд╛ рд╣реИред)
рдРрд╕рд╛ рдкрдврд╝рдирд╛ рд╕реНрд╡рд╛рднрд╛рд╡рд┐рдХ рд▓рдЧрддрд╛ рд╣реИ
рдЖрдЗрдП рд╣рдореЗрдВ Foo bar baz
рд▓рд┐рдП рдПрдХ рдЙрджрд╛рд╣рд░рдг рдЪреБрдирдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред рдпрджрд┐ context
рд╕рдВрддреБрд╖реНрдЯ рд╣реИ, рддреЛ рдЖрдк рдЗрд╕ рдЙрджрд╛рд╣рд░рдг рдХрд╛ рдЪрдпрди рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ рдмрд╢рд░реНрддреЗ рдХрд┐ bar
рдФрд░ barPattern
рдФрд░ bazPattern
рдЕрдиреБрд░реВрдк bazPattern
ред
рд╣рд╛рд▓рд╛рдБрдХрд┐, рдпрд╣ рдПрдХ рдЧрд▓рдд рд╡реНрдпрд╛рдЦреНрдпрд╛ рд╣реИ, рдФрд░ рдЗрд╕рдХреЗ рдареАрдХ рд╡рд┐рдкрд░реАрдд рд╣реИ:
рдЖрдЗрдП рд╣рдореЗрдВ Foo bar baz
рд▓рд┐рдП рдПрдХ рдЙрджрд╛рд╣рд░рдг рдЪреБрдирдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред рдпрджрд┐ bar
рдФрд░ bazPattern
, barPattern
рдФрд░ bazPattern
рдЕрдиреБрд░реВрдк рд╣реИрдВ, рддреЛ рд╣рдо рдЗрд╕ рдЙрджрд╛рд╣рд░рдг рдХрд╛ рдЪрдпрди рдХрд░рддреЗ рд╣реИрдВ рдФрд░ рд╕реНрдерд┐рд░рд╛рдВрдХ рдХреА рд╕реВрдЪреА рдореЗрдВ context
рдЬреЛрдбрд╝рддреЗ рд╣реИрдВ рдЬрд┐рдиреНрд╣реЗрдВ рд╣рд▓ рдХрд┐рдпрд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдПред
рдЕрдм рдпрд╣ рд╕реНрдкрд╖реНрдЯ рд╣реИ рдХрд┐ рд╕рдорд╕реНрдпрд╛ рдХреНрдпрд╛ рд╣реИ рдЖрдЗрдП рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдЙрджрд╛рд╣рд░рдгреЛрдВ рдкрд░ рдПрдХ рдирдЬрд╝рд░ рдбрд╛рд▓реЗрдВ:
instance GHas part l => GHas part (l :*: r) where gextract (l :*: _) = gextract l instance GHas part r => GHas part (l :*: r) where gextract (_ :*: r) = gextract r
рдЙрдирдХреЗ рдкрд╛рд╕ рдПрдХ рд╣реА рдЙрджрд╛рд╣рд░рдг рдкреНрд░рдореБрдЦ рд╣реИрдВ, рдЗрд╕рд▓рд┐рдП рдХреЛрдИ рдЖрд╢реНрдЪрд░реНрдп рдирд╣реАрдВ рдХрд┐ рд╡реЗ рдПрдХ рджреВрд╕рд░реЗ рдХреЛ рдХрд╛рдЯрддреЗ рд╣реИрдВ! рдЗрд╕рдХреЗ рдЕрд▓рд╛рд╡рд╛, рдЙрдирдореЗрдВ рд╕реЗ рдХреЛрдИ рднреА рдЕрдиреНрдп рдХреА рддреБрд▓рдирд╛ рдореЗрдВ рдЕрдзрд┐рдХ рд╡рд┐рд╢рд┐рд╖реНрдЯ рдирд╣реАрдВ рд╣реИред
рдЗрд╕рдХреЗ рдЕрд▓рд╛рд╡рд╛, рдЗрди рдЙрджрд╛рд╣рд░рдгреЛрдВ рдХреЛ рдХрд┐рд╕реА рддрд░рд╣ рд╕реЗ рдкрд░рд┐рд╖реНрдХреГрдд рдХрд░рдиреЗ рдХрд╛ рдХреЛрдИ рддрд░реАрдХрд╛ рдирд╣реАрдВ рд╣реИ рддрд╛рдХрд┐ рд╡реЗ рдУрд╡рд░рд▓реИрдк рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рд╕рдВрдШрд░реНрд╖ рди рдХрд░реЗрдВред рдЦреИрд░, рдЗрд╕рдХреЗ рдЕрд▓рд╛рд╡рд╛ рдФрд░ GHas
рдорд╛рдкрджрдВрдбреЛрдВ рдХреЛ рдЬреЛрдбрд╝рдирд╛ред
рдЕрднрд┐рд╡реНрдпрдХреНрдд рдкреНрд░рдХрд╛рд░ рдмрдЪрд╛рд╡ рдХреЗ рд▓рд┐рдП рднрд╛рдЧрддреЗ рд╣реИрдВ!
рд╕рдорд╕реНрдпрд╛ рдХрд╛ рд╣рд▓ "рдкрде" рдХреА рдЧрдгрдирд╛ рд╣рдорд╛рд░реЗ рд▓рд┐рдП рдмреНрдпрд╛рдЬ рдХреЗ рдореВрд▓реНрдп рд╕реЗ рдкрд╣рд▓реЗ рдХрд░рдирд╛ рд╣реИ, рдФрд░ рдЙрджрд╛рд╣рд░рдгреЛрдВ рдХреА рдкрд╕рдВрдж рдХреЛ рдирд┐рд░реНрджреЗрд╢рд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЗрд╕ рд░рд╛рд╕реНрддреЗ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдирд╛ рд╣реИред
рдЪреВрдВрдХрд┐ рд╣рдо рдпреЛрдЧ рдкреНрд░рдХрд╛рд░реЛрдВ рдХрд╛ рд╕рдорд░реНрдерди рдирд╣реАрдВ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рд╕рд╣рдордд рдереЗ, рдЗрд╕рд▓рд┐рдП рдПрдХ рдкрде рд╢рд╛рдмреНрджрд┐рдХ рдЕрд░реНрде рдореЗрдВ рдЙрддреНрдкрд╛рдж рдкреНрд░рдХрд╛рд░реЛрдВ рдореЗрдВ рдмрд╛рдПрдБ рдпрд╛ рджрд╛рдПрдБ рдШреБрдорд╛рд╡ рдХрд╛ рдПрдХ рдХреНрд░рдо рд╣реИ (рдЬреЛ рдХрд┐ рдПрдХ рдЬреЛрдбрд╝реА рдХреЗ рдкрд╣рд▓реЗ рдпрд╛ рджреВрд╕рд░реЗ рдШрдЯрдХ рдХреА рдкрд╕рдВрдж рд╣реИ), рдПрдХ рдмрдбрд╝реЗ "HERE" рдкреЙрдЗрдВрдЯрд░ рдХреЗ рд╕рд╛рде рд╕рдорд╛рдкреНрдд рд╣реЛрддрд╛ рд╣реИ, рдЬреИрд╕реЗ рд╣реА рд╣рдореЗрдВ рд╡рд╛рдВрдЫрд┐рдд рдкреНрд░рдХрд╛рд░ рдорд┐рд▓рддреЗ рд╣реИрдВред ред рд╣рдо рдЗрд╕реЗ рд▓рд┐рдЦрддреЗ рд╣реИрдВ:
data Path = L Path | R Path | Here deriving (Show)
рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдПрдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдкреНрд░рдХрд╛рд░реЛрдВ рдкрд░ рд╡рд┐рдЪрд╛рд░ рдХрд░реЗрдВ:
data DbConfig = DbConfig { dbAddress :: DbAddress , dbUsername :: Username , dbPassword :: Password } data AppConfig = AppConfig { dbConfig :: DbConfig , webServerConfig :: WebServerConfig , cronConfig :: CronConfig }
AppConfig
рд╕реЗ рд░рд╛рд╕реНрддреЛрдВ рдХреЗ рдХреБрдЫ рдЙрджрд╛рд╣рд░рдг рдХреНрдпрд╛ рд╣реИрдВ?
L Here
DbConfig
L Here
редWebServerConfig
R (L Here)
редCronConfig
рдХреЛ R (R Here)
редDbAddress
L (L Here)
ред
рд╡рд╛рдВрдЫрд┐рдд рдкреНрд░рдХрд╛рд░ рдХреЗ рдореВрд▓реНрдп рдХреА рдЦреЛрдЬ рдХрд╛ рдкрд░рд┐рдгрд╛рдо рдХреНрдпрд╛ рд╣реЛ рд╕рдХрддрд╛ рд╣реИ? рджреЛ рд╡рд┐рдХрд▓реНрдк рд╕реНрдкрд╖реНрдЯ рд╣реИрдВ: рд╣рдо рдЗрд╕реЗ рдвреВрдВрдв рд╕рдХрддреЗ рд╣реИрдВ рдпрд╛ рдирд╣реАрдВ рдкрд╛ рд╕рдХрддреЗ рд╣реИрдВред рд▓реЗрдХрд┐рди рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ, рд╕рдм рдХреБрдЫ рдереЛрдбрд╝рд╛ рдЕрдзрд┐рдХ рдЬрдЯрд┐рд▓ рд╣реИ: рд╣рдо рдЗрд╕ рдкреНрд░рдХрд╛рд░ рдХреЗ рдПрдХ рд╕реЗ рдЕрдзрд┐рдХ рдореВрд▓реНрдп рдкрд╛ рд╕рдХрддреЗ рд╣реИрдВред рд╕реНрдкрд╖реНрдЯ рд░реВрдк рд╕реЗ рдЗрд╕ рд╡рд┐рд╡рд╛рджрд╛рд╕реНрдкрдж рдорд╛рдорд▓реЗ рдореЗрдВ рд╕рдмрд╕реЗ рд╕рдордЭрджрд╛рд░ рд╡реНрдпрд╡рд╣рд╛рд░ рднреА рдПрдХ рддреНрд░реБрдЯрд┐ рд╕рдВрджреЗрд╢ рд╣реЛрдЧрд╛ред рдХрд┐рд╕реА рд╡рд┐рд╢реЗрд╖ рдореВрд▓реНрдп рдХреЗ рдХрд┐рд╕реА рднреА рд╡рд┐рдХрд▓реНрдк рдореЗрдВ рдПрдХ рдирд┐рд╢реНрдЪрд┐рдд рдорд╛рддреНрд░рд╛ рдореЗрдВ рдпрд╛рджреГрдЪреНрдЫрд┐рдХрддрд╛ рд╣реЛрдЧреАред
рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ, рд╣рдорд╛рд░реЗ рдорд╛рдирдХ рд╡реЗрдм рд╕реЗрд╡рд╛ рдЙрджрд╛рд╣рд░рдг рдкрд░ рд╡рд┐рдЪрд╛рд░ рдХрд░реЗрдВред рдпрджрд┐ рдХреЛрдИ рд╡реНрдпрдХреНрддрд┐ рдкреНрд░рдХрд╛рд░ (Host, Port)
рдХрд╛ рдорд╛рди рдкреНрд░рд╛рдкреНрдд рдХрд░рдирд╛ рдЪрд╛рд╣рддрд╛ рд╣реИ, рддреЛ рдХреНрдпрд╛ рдпрд╣ рдбреЗрдЯрд╛рдмреЗрд╕ рд╕рд░реНрд╡рд░ рдХрд╛ рдкрддрд╛ рдпрд╛ рд╡реЗрдм рд╕рд░реНрд╡рд░ рдХрд╛ рдкрддрд╛ рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдП? рдЗрд╕реЗ рдЬреЛрдЦрд┐рдо рдореЗрдВ рдирд╣реАрдВ рдбрд╛рд▓рдирд╛ рдмреЗрд╣рддрд░ рд╣реИред
рдХрд┐рд╕реА рднреА рд╕реНрдерд┐рддрд┐ рдореЗрдВ, рдЖрдЗрдП рдЗрд╕реЗ рдХреЛрдб рдореЗрдВ рд╡реНрдпрдХреНрдд рдХрд░реЗрдВ:
data MaybePath = NotFound | Conflict | Found Path deriving (Show)
рд╣рдо NotFound
рдФрд░ Conflict
рдЕрд▓рдЧ NotFound
, рдХреНрдпреЛрдВрдХрд┐ рдЗрди рдорд╛рдорд▓реЛрдВ рдХреА рд╣реИрдВрдбрд▓рд┐рдВрдЧ рдореМрд▓рд┐рдХ рд░реВрдк рд╕реЗ рднрд┐рдиреНрди рд╣реЛрддреА рд╣реИ: рдпрджрд┐ рд╣рдо рдЕрдкрдиреЗ рдЙрддреНрдкрд╛рдж рдкреНрд░рдХрд╛рд░ рдХреА рд╢рд╛рдЦрд╛рдУрдВ рдореЗрдВ рд╕реЗ рдПрдХ рдореЗрдВ NotFound
рдкреНрд░рд╛рдкреНрдд NotFound
, рддреЛ рдпрд╣ рдХрд┐рд╕реА рдЕрдиреНрдп рд╢рд╛рдЦрд╛ рдореЗрдВ рд╡рд╛рдВрдЫрд┐рдд рдорд╛рди рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЪреЛрдЯ рдирд╣реАрдВ рдкрд╣реБрдВрдЪрд╛рдПрдЧрд╛, рдЬрдмрдХрд┐ рдХрд┐рд╕реА рднреА рд╢рд╛рдЦрд╛ рдореЗрдВ Conflict
рдХрд╛ рддреБрд░рдВрдд рдкреВрд░реНрдг рдЕрд░реНрде рд╣реИ рдПрдХ рд╡рд┐рдлрд▓рддрд╛ред
рдЕрдм рд╣рдо рдЙрддреНрдкрд╛рдж рдкреНрд░рдХрд╛рд░реЛрдВ рдХреЗ рдПрдХ рд╡рд┐рд╢реЗрд╖ рдорд╛рдорд▓реЗ рдкрд░ рд╡рд┐рдЪрд╛рд░ рдХрд░рддреЗ рд╣реИрдВ (рдЬреЛ, рдЬреИрд╕рд╛ рдХрд┐ рд╣рдо рд╕рд╣рдордд рдереЗ, рд╣рдо рдЬреЛрдбрд╝реЗ рдХреЗ рд░реВрдк рдореЗрдВ рдорд╛рдирддреЗ рд╣реИрдВ)ред рдЙрдирдореЗрдВ рд╡рд╛рдВрдЫрд┐рдд рдкреНрд░рдХрд╛рд░ рдХрд╛ рдореВрд▓реНрдп рдХреИрд╕реЗ рдвреВрдВрдвреЗрдВ? рдЖрдк рдПрдХ рдЬреЛрдбрд╝реА рдХреЗ рдкреНрд░рддреНрдпреЗрдХ рдШрдЯрдХ рдореЗрдВ рдкреБрдирд░рд╛рд╡рд░реНрддреА рд░реВрдк рд╕реЗ рдЦреЛрдЬ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ p2
рдХреНрд░рдорд╢рдГ p1
рдФрд░ p2
рдкрд░рд┐рдгрд╛рдо рдкреНрд░рд╛рдкреНрдд рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ, рдФрд░ рдлрд┐рд░ рдХрд┐рд╕реА рддрд░рд╣ рдЙрдиреНрд╣реЗрдВ рдЬреЛрдбрд╝ рд╕рдХрддреЗ рд╣реИрдВред
рдЪреВрдВрдХрд┐ рд╣рдо рд╕рдВрдХрд▓рди рдХреЗ рджреМрд░рд╛рди рд╣реЛрдиреЗ рд╡рд╛рд▓реЗ рдЯрд╛рдЗрдордХреНрд▓рд╕ рдХреЗ рдЙрджрд╛рд╣рд░рдгреЛрдВ рдХреЗ рд╡рд┐рдХрд▓реНрдк рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдмрд╛рдд рдХрд░ рд░рд╣реЗ рд╣реИрдВ, рд╣рдореЗрдВ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рд╕рдВрдХрд▓рди рдХреА рдЧрдгрдирд╛ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ, рдЬреЛ рдХрд┐ рд╣рд╛рд╕реНрдХреЗрд▓ рдореЗрдВ рдкреНрд░рдХрд╛рд░реЛрдВ рдкрд░ рд╕рдВрдЧрдгрдирд╛ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рд╡реНрдпрдХреНрдд рдХрд┐рдП рдЬрд╛рддреЗ рд╣реИрдВ (рднрд▓реЗ рд╣реА DataKinds
рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдмреНрд░рд╣реНрдорд╛рдВрдб рдореЗрдВ рдЙрдард╛рдП рдЧрдП рд╢рдмреНрджреЛрдВ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдкреНрд░рддрд┐рдирд┐рдзрд┐рддреНрд╡ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ)ред рддрджрдиреБрд╕рд╛рд░, рдкреНрд░рдХрд╛рд░реЛрдВ рдкрд░ рдЗрд╕ рддрд░рд╣ рдХреЗ рдПрдХ рдХрд╛рд░реНрдп рдХреЛ рдкреНрд░рдХрд╛рд░ рдкрд░рд┐рд╡рд╛рд░ рдХреЗ рд░реВрдк рдореЗрдВ рджрд░реНрд╢рд╛рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ:
type family Combine p1 p2 where Combine ('Found path) 'NotFound = 'Found ('L path) Combine 'NotFound ('Found path) = 'Found ('R path) Combine 'NotFound 'NotFound = 'NotFound Combine _ _ = 'Conflict
рдпрд╣ рдлрд╝рдВрдХреНрд╢рди рдХрдИ рдорд╛рдорд▓реЛрдВ рдХрд╛ рдкреНрд░рддрд┐рдирд┐рдзрд┐рддреНрд╡ рдХрд░рддрд╛ рд╣реИ:
- рдпрджрд┐ рдкреБрдирд░рд╛рд╡рд░реНрддреА рдЦреЛрдЬреЛрдВ рдореЗрдВ рд╕реЗ рдПрдХ рд╕рдлрд▓ рд╣реИ, рдФрд░ рджреВрд╕рд░рд╛
NotFound
рд╣реИ, рддреЛ рд╣рдо рд╕рдлрд▓ рдЦреЛрдЬ рд╕реЗ рд░рд╛рд╕реНрддрд╛ NotFound
рд╣реИрдВ рдФрд░ рд╕рд╣реА рджрд┐рд╢рд╛ рдореЗрдВ рдореЛрдбрд╝ рдХреЛ рдЬреЛрдбрд╝рддреЗ рд╣реИрдВред - рдпрджрд┐ рджреЛрдиреЛрдВ рдкреБрдирд░рд╛рд╡рд░реНрддреА рдЦреЛрдЬ
NotFound
рд╕рд╛рде рд╕рдорд╛рдкреНрдд рд╣реЛ NotFound
, рддреЛ рдЬрд╛рд╣рд┐рд░ рд╣реИ рдкреВрд░реА рдЦреЛрдЬ NotFound
рд╕рд╛рде рд╕рдорд╛рдкреНрдд рд╣реЛ NotFound
ред - рдХрд┐рд╕реА рдЕрдиреНрдп рдорд╛рдорд▓реЗ рдореЗрдВ, рд╣рдо
Conflict
ред
рдЕрдм рд╣рдо рдПрдХ рдЯрд┐рдк-рд╕реНрддрд░реАрдп рдлрд╝рдВрдХреНрд╢рди рд▓рд┐рдЦреЗрдВрдЧреЗ рдЬреЛ рдХрд┐ рдкрд╛рдпрд╛ рдЬрд╛рдиреЗ рд╡рд╛рд▓рд╛ part
рд▓реЗрддрд╛ рд╣реИ, рдФрд░ рдЙрд╕ рдкреНрд░рдХрд╛рд░ рдХрд╛ рдПрдХ Generic
рдкреНрд░рддрд┐рдирд┐рдзрд┐рддреНрд╡ рдЬрд┐рд╕рдореЗрдВ part
рдвреВрдВрдврдирд╛ рд╣реИ, рдФрд░ рдЦреЛрдЬ рдХрд░рддрд╛ рд╣реИ:
type family Search part (grecord :: k -> *) :: MaybePath where Search part (K1 _ part) = 'Found 'Here Search part (K1 _ other) = 'NotFound Search part (M1 _ _ x) = Search part x Search part (l :*: r) = Combine (Search part l) (Search part r) Search _ _ = 'NotFound
рдзреНрдпрд╛рди рджреЗрдВ рдХрд┐ рд╣рдореЗрдВ GHas
рд╕рд╛рде рд╣рдорд╛рд░реЗ рдкрд┐рдЫрд▓реЗ рдкреНрд░рдпрд╛рд╕ рдХреЗ рдЕрд░реНрде рдореЗрдВ рдХреБрдЫ рд╕рдорд╛рди рдерд╛ред рдпрд╣ рдЙрдореНрдореАрдж рдХреА рдЬрд╛рдиреА рд╣реИ, рдХреНрдпреЛрдВрдХрд┐ рд╣рдо рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдПрд▓реНрдЧреЛрд░рд┐рдереНрдо рдХреЛ рдкреБрди: рдкреЗрд╢ рдХрд░ рд░рд╣реЗ рд╣реИрдВ рдЬрд┐рд╕реЗ рд╣рдордиреЗ рдЯрд╛рдЗрдордХреНрд▓рд╕ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рд╡реНрдпрдХреНрдд рдХрд░рдиреЗ рдХреА рдХреЛрд╢рд┐рд╢ рдХреА рдереАред
GHas
, рддреЛ рд╣рдорд╛рд░реЗ рд▓рд┐рдП рдЬреЛ рдХреБрдЫ рднреА рд╣реИ рд╡рд╣ рдЗрд╕ рд╡рд░реНрдЧ рдореЗрдВ рдПрдХ рдЕрддрд┐рд░рд┐рдХреНрдд рдкреИрд░рд╛рдореАрдЯрд░ рдЬреЛрдбрд╝рдиреЗ рдХреЗ рд▓рд┐рдП рд╣реИ, рдЬреЛ рдкрд╣рд▓реЗ рдкрд╛рдП рдЧрдП рдкрде рдХреЗ рд▓рд┐рдП рдЬрд┐рдореНрдореЗрджрд╛рд░ рд╣реИ, рдФрд░ рдЬреЛ рд╡рд┐рд╢рд┐рд╖реНрдЯ рдЙрджрд╛рд╣рд░рдгреЛрдВ рдХрд╛ рдЪрдпрди рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХрд╛рдо рдХрд░реЗрдЧрд╛:
class GHas (path :: Path) part grecord where gextract :: Proxy path -> grecord p -> part
рд╣рдордиреЗ gextract
рд▓рд┐рдП рдПрдХ рдЕрддрд┐рд░рд┐рдХреНрдд рддрд░реНрдХ рднреА рдЬреЛрдбрд╝рд╛ рддрд╛рдХрд┐ рд╕рдВрдХрд▓рдХ рджрд┐рдП рдЧрдП рдкрде рдХреЗ рд▓рд┐рдП рд╕рд╣реА рдЙрджрд╛рд╣рд░рдг рдХрд╛ рдЪрдпрди рдХрд░ рд╕рдХреЗ (рдЬрд┐рд╕реЗ рдЗрд╕рдХреЗ рд▓рд┐рдП рдлрд╝рдВрдХреНрд╢рди рд╣рд╕реНрддрд╛рдХреНрд╖рд░ рдореЗрдВ рдЙрд▓реНрд▓реЗрдЦ рдХрд┐рдпрд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдП)ред
рдЕрдм рдЙрджрд╛рд╣рд░рдг рд▓рд┐рдЦрдирд╛ рдмрд╣реБрдд рдЖрд╕рд╛рди рд╣реИ:
instance GHas 'Here record (K1 i record) where gextract _ (K1 x) = x instance GHas path part record => GHas path part (M1 it record) where gextract proxy (M1 x) = gextract proxy x instance GHas path part l => GHas ('L path) part (l :*: r) where gextract _ (l :*: _) = gextract (Proxy :: Proxy path) l instance GHas path part r => GHas ('R path) part (l :*: r) where gextract _ (_ :*: r) = gextract (Proxy :: Proxy path) r
рджрд░рдЕрд╕рд▓, рд╣рдо рдХреЗрд╡рд▓ рдЙрд╕ рдкрде рдХреЗ рдЖрдзрд╛рд░ рдкрд░ рд╡рд╛рдВрдЫрд┐рдд рдЙрджрд╛рд╣рд░рдг рдХрд╛ рдЪрдпрди рдХрд░рддреЗ рд╣реИрдВ рдЬрд┐рд╕ path
рдЧрдгрдирд╛ рд╣рдордиреЗ рдкрд╣рд▓реЗ рдХреА рдереАред
рдЕрдм extract :: record -> part
рд╣рдорд╛рд░реЗ default
рдХреНрд░рд┐рдпрд╛рдиреНрд╡рдпрди рдХреЛ рдХреИрд╕реЗ рд▓рд┐рдЦреЗрдВ extract :: record -> part
Has
рдХреНрд▓рд╛рд╕ рдореЗрдВ extract :: record -> part
рдлрдВрдХреНрд╢рди? рд╣рдорд╛рд░реА рдХрдИ рд╢рд░реНрддреЗрдВ рд╣реИрдВ:
record
Generic
рдХреЛ рд▓рд╛рдЧреВ рдХрд░рдирд╛ рдЪрд╛рд╣рд┐рдП рддрд╛рдХрд┐ рдЬреЗрдиреЗрд░рд┐рдХ рддрдВрддреНрд░ рд▓рд╛рдЧреВ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХреЗ, рдЗрд╕рд▓рд┐рдП рд╣рдореЗрдВ Generic record
рдорд┐рд▓рддрд╛ рд╣реИредSearch
рдлрд╝рдВрдХреНрд╢рди рдХреЛ record
(рдпрд╛ рдмрд▓реНрдХрд┐, record
рдХреЗ Generic
рдкреНрд░рддрд┐рдирд┐рдзрд┐рддреНрд╡ рдореЗрдВ, рдЬрд┐рд╕реЗ Rep record
рд░реВрдк рдореЗрдВ рд╡реНрдпрдХреНрдд рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ) part
рдорд┐рд▓рдирд╛ рдЪрд╛рд╣рд┐рдПред рдХреЛрдб рдореЗрдВ, рдпрд╣ рдереЛрдбрд╝рд╛ рдФрд░ рдЕрд╕рд╛рдорд╛рдиреНрдп рд▓рдЧрддрд╛ рд╣реИ: Search part (Rep record) ~ 'Found path
ред рдЗрд╕ рд░рд┐рдХреЙрд░реНрдб рдХрд╛ рдорддрд▓рдм рдпрд╣ рд╣реИ рдХрд┐ Search part (Rep record)
рдХрд╛ рдкрд░рд┐рдгрд╛рдо 'Found path
рдХреБрдЫ path
рд▓рд┐рдП 'Found path
path
(рдЬреЛ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ, рд╣рдорд╛рд░реЗ рд▓рд┐рдП рджрд┐рд▓рдЪрд╕реНрдк рд╣реИ) рдХреЗ рдмрд░рд╛рдмрд░ рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдПред- рд╣рдореЗрдВ
part
рдХреЗ рд╕рд╛рде-рд╕рд╛рде рдЕрдВрддрд┐рдо рдЪрд░рдг рд╕реЗ record
рдФрд░ path
рдХреЗ рд╕рд╛рдорд╛рдиреНрдп рдкреНрд░рддрд┐рдирд┐рдзрд┐рддреНрд╡ рдХреЗ рд╕рд╛рде GHas
рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдореЗрдВ рд╕рдХреНрд╖рдо рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдП, рдЬреЛ рдХрд┐ GHas path part (Rep record)
рдореЗрдВ рдмрджрд▓ рдЬрд╛рддрд╛ рд╣реИред
рд╣рдо рдЕрдВрддрд┐рдо рджреЛ рд╕реНрдерд┐рд░рд╛рдВрдХ рдХрдИ рдмрд╛рд░ рдорд┐рд▓реЗрдВрдЧреЗ, рдЗрд╕рд▓рд┐рдП рдЙрдиреНрд╣реЗрдВ рдЕрд▓рдЧ рдХрд╛рдВрд╕реНрдЯреЗрдмрд▓ рдкрд░реНрдпрд╛рдпрд╡рд╛рдЪреА рдХрд╣рдирд╛ рдЙрдкрдпреЛрдЧреА рд╣реИ:
type SuccessfulSearch part record path = (Search part (Rep record) ~ 'Found path, GHas path part (Rep record))
рдЗрд╕ рдкрд░реНрдпрд╛рдпрд╡рд╛рдЪреА рдХреЛ рджреЗрдЦрддреЗ рд╣реБрдП, рд╣рдо рдкреНрд░рд╛рдкреНрдд рдХрд░рддреЗ рд╣реИрдВ
class Has part record where extract :: record -> part default extract :: forall path. (Generic record, SuccessfulSearch part record path) => record -> part extract = gextract (Proxy :: Proxy path) . from
рдЕрдм рд╕рдм рдХреБрдЫ!
рдЬреЗрдиреЗрд░рд┐рдХ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдирд╛
рдЗрди рд╕рднреА рдХрд╛рд░реНрдпреЛрдВ рдХреЛ рджреЗрдЦрдиреЗ рдХреЗ рд▓рд┐рдП, рд╣рдо рдбрдореА рдХреЗ рд▓рд┐рдП рдХреБрдЫ рд╕рд╛рдорд╛рдиреНрдп рдЙрджрд╛рд╣рд░рдг рд▓рд┐рдЦреЗрдВрдЧреЗ:
instance SuccessfulSearch a (a0, a1) path => Has a (a0, a1) instance SuccessfulSearch a (a0, a1, a2) path => Has a (a0, a1, a2) instance SuccessfulSearch a (a0, a1, a2, a3) path => Has a (a0, a1, a2, a3)
рдпрд╣рд╛рдБ SuccessfulSearch a (a0, ..., an) path
рдЗрд╕ рддрдереНрдп рдХреЗ рд▓рд┐рдП рдЬрд┐рдореНрдореЗрджрд╛рд░ рд╣реИ рдХрд┐ a0, ..., an
рдмреАрдЪ a0, ..., an
рдмрд╛рд░ рд╣реЛрддрд╛ рд╣реИред
рд╣реЛ рд╕рдХрддрд╛ рд╣реИ рдХрд┐ рдЕрдм рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдЕрдЪреНрдЫрд╛ рдкреБрд░рд╛рдирд╛ рд╣реЛ
data AppConfig = AppConfig { dbConfig :: DbConfig , webServerConfig :: WebServerConfig , cronConfig :: CronConfig }
рдФрд░ рд╣рдо Has DbConfig
, Has WebServerConfig
рдФрд░ Has CronConfig
рдХрд╛ рдЙрддреНрдкрд╛рджрди рдХрд░рдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВред рдпрд╣ DeriveGeneric
рдФрд░ DeriveAnyClass
рдХреЛ рд╢рд╛рдорд┐рд▓ рдХрд░рдиреЗ рдФрд░ рд╕рд╣реА deriving
рдШреЛрд╖рдгрд╛ рдХреЛ рдЬреЛрдбрд╝рдиреЗ рдХреЗ рд▓рд┐рдП рдкрд░реНрдпрд╛рдкреНрдд рд╣реИ:
data AppConfig = AppConfig { dbConfig :: DbConfig , webServerConfig :: WebServerConfig , cronConfig :: CronConfig } deriving (Generic, Has DbConfig, Has WebServerConfig, Has CronConfig)
рд╣рдо рднрд╛рдЧреНрдпрд╢рд╛рд▓реА рд╣реИрдВ (рдпрд╛ рд╣рдо рдкрд░реНрдпрд╛рдкреНрдд рд░реВрдк рд╕реЗ рдЖрдирдВрджрд┐рдд рдереЗ) Has
рд▓рд┐рдП рддрд░реНрдХреЛрдВ рдХреЛ рд╡реНрдпрд╡рд╕реНрдерд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рддрд╛рдХрд┐ рдиреЗрд╕реНрдЯреЗрдб рдкреНрд░рдХрд╛рд░ рдХрд╛ рдирд╛рдо рдкрд╣рд▓реЗ рдЖрдП, рддрд╛рдХрд┐ рд╣рдо DeriveAnyClass
рдХреЛ рдХрдо рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП DeriveAnyClass
рддрдВрддреНрд░ рдкрд░ рднрд░реЛрд╕рд╛ рдХрд░ DeriveAnyClass
ред
рд╕реБрд░рдХреНрд╖рд╛ рдкрд╣рд▓реЗ рдЖрддреА рд╣реИ
рдпрджрд┐ рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдХреЛрдИ рдкреНрд░рдХрд╛рд░ рдирд╣реАрдВ рд╣реИ рддреЛ рдХреНрдпрд╛ рд╣реЛрдЧрд╛?
data AppConfig = AppConfig { dbConfig :: DbConfig , webServerConfig :: WebServerConfig } deriving (Generic, Has CronConfig)
рдирд╣реАрдВ, рд╣рдореЗрдВ рдЯрд╛рдЗрдк рдкрд░рд┐рднрд╛рд╖рд╛ рдХреЗ рдмрд┐рдВрджреБ рдкрд░ рдПрдХ рддреНрд░реБрдЯрд┐ рдорд┐рд▓рддреА рд╣реИ:
Spec.hs:35:24: error: тАв Couldn't match type ''NotFound' with ''Found path0' arising from the 'deriving' clause of a data type declaration тАв When deriving the instance for (Has CronConfig AppConfig) | 35 | } deriving (Generic, Has CronConfig) | ^^^^^^^^^^^^^^
рдорд┐рддреНрд░рд╡рдд рддреНрд░реБрдЯрд┐ рд╕рдВрджреЗрд╢ рдирд╣реАрдВ, рд▓реЗрдХрд┐рди рдпрд╣рд╛рдВ рддрдХ тАЛтАЛрдХрд┐ рдЖрдк рдЕрднреА рднреА рдпрд╣ рд╕рдордЭ рд╕рдХрддреЗ рд╣реИрдВ рдХрд┐ рд╕рдорд╕реНрдпрд╛ рдХреНрдпрд╛ рд╣реИ: рд╡рд┐рд╖рдо рдЖрд╡реГрддреНрддрд┐ NotFound
рд╡рд┐рд╖рдо рдЖрд╡реГрддреНрддрд┐ CronConfig
ред
рдХреНрдпрд╛ рд╣реЛрдЧрд╛ рдпрджрд┐ рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдПрдХ рд╣реА рдкреНрд░рдХрд╛рд░ рдХреЗ рдХрдИ рдХреНрд╖реЗрддреНрд░ рд╣реИрдВ?
data AppConfig = AppConfig { prodDbConfig :: DbConfig , qaDbConfig :: DbConfig , webServerConfig :: WebServerConfig , cronConfig :: CronConfig } deriving (Generic, Has DbConfig)
рдЬреИрд╕рд╛ рдХрд┐ рдЕрдкреЗрдХреНрд╖рд┐рдд рдерд╛: рдирд╣реАрдВ
Spec.hs:37:24: error: тАв Couldn't match type ''Conflict' with ''Found path0' arising from the 'deriving' clause of a data type declaration тАв When deriving the instance for (Has DbConfig AppConfig) | 37 | } deriving (Generic, Has DbConfig) | ^^^^^^^^^^^^
рд╕рдм рдХреБрдЫ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдЕрдЪреНрдЫрд╛ рд▓рдЧрддрд╛ рд╣реИред
рд╕рдВрдХреНрд╖реЗрдк рдореЗрдВ рджреЗрдирд╛
рдЗрд╕рд▓рд┐рдП, рд╣рдо рдкреНрд░рд╕реНрддрд╛рд╡рд┐рдд рдкрджреНрдзрддрд┐ рдХреЛ рд╕рдВрдХреНрд╖реЗрдк рдореЗрдВ рддреИрдпрд╛рд░ рдХрд░рдиреЗ рдХрд╛ рдкреНрд░рдпрд╛рд╕ рдХрд░реЗрдВрдЧреЗред
рдорд╛рди рд▓реАрдЬрд┐рдП рдХрд┐ рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдХреБрдЫ рдкреНрд░рдХрд╛рд░ рдХреЗ рдЯрд╛рдЗрдкрдХреНрд▓рд╛рд╕ рд╣реИрдВ, рдФрд░ рд╣рдо рдХреБрдЫ рдкреБрдирд░рд╛рд╡рд░реНрддреА рдирд┐рдпрдореЛрдВ рдХреЗ рдЕрдиреБрд╕рд╛рд░ рдЗрд╕рдХреЗ рдЙрджрд╛рд╣рд░рдгреЛрдВ рдХреЛ рд╕реНрд╡рдЪрд╛рд▓рд┐рдд рд░реВрдк рд╕реЗ рдкреНрд░рджрд░реНрд╢рд┐рдд рдХрд░рдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВред рддрдм рд╣рдо рдЕрд╕реНрдкрд╖реНрдЯрддрд╛рдУрдВ рд╕реЗ рдмрдЪ рд╕рдХрддреЗ рд╣реИрдВ (рдФрд░ рдЖрдорддреМрд░ рдкрд░ рдЗрди рдирд┐рдпрдореЛрдВ рдХреЛ рд╡реНрдпрдХреНрдд рдХрд░рддреЗ рд╣реИрдВ рдпрджрд┐ рд╡реЗ nontrivial рд╣реИрдВ рдФрд░ рдЙрджрд╛рд╣рд░рдгреЛрдВ рдХреЛ рд╣рд▓ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдорд╛рдирдХ рддрдВрддреНрд░ рдореЗрдВ рдлрд┐рдЯ рдирд╣реАрдВ рд╣реЛрддреЗ рд╣реИрдВ) рдирд┐рдореНрдирд╛рдиреБрд╕рд╛рд░ рд╣реИрдВ:
- рд╣рдо рдПрдХ рдкреНрд░реЗрд░рдХ рдбреЗрдЯрд╛ рдкреНрд░рдХрд╛рд░
T
рдХреЗ рд░реВрдк рдореЗрдВ рдкреБрдирд░рд╛рд╡рд░реНрддреА рдирд┐рдпрдореЛрдВ рдХреЛ рд╕рд╛рдВрдХреЗрддрд┐рдХ рд╢рдмреНрджреЛрдВ рдореЗрдВ рдмрджрд▓рдирд╛ T
- рд╣рдо рдЗрд╕ рдкреНрд░рдХрд╛рд░
T
(рдпрд╛, рд╣рд╛рд╕реНрдХреЗрд▓ рдХреЗ рд╕рдВрджрд░реНрдн рдореЗрдВ, рдЯрд╛рдЗрдк v
рдкреНрд░рдХрд╛рд░ - рдЬрд╣рд╛рдВ рдореЗрд░реЗ рдЖрд╢реНрд░рд┐рдд рдкреНрд░рдХрд╛рд░ рд╣реИрдВ) рдХреЗ рдкреНрд░рд╛рд░рдВрднрд┐рдХ рдЧрдгрдирд╛ рдХреЗ рд▓рд┐рдП рдкреНрд░рдХрд╛рд░реЛрдВ (рдкреНрд░рдХрд╛рд░ рдХреЗ рдкрд░рд┐рд╡рд╛рд░ рдХреЗ рд░реВрдк рдореЗрдВ) рдкрд░ рдПрдХ рдлрд╝рдВрдХреНрд╢рди рд▓рд┐рдЦреЗрдВрдЧреЗ, рдЬрд┐рд╕рдореЗрдВ рдЙрди рдЪрд░рдгреЛрдВ рдХреЗ рд╡рд┐рд╢рд┐рд╖реНрдЯ рдЕрдиреБрдХреНрд░рдо рдХрд╛ рд╡рд░реНрдгрди рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ рдЬрд┐рдиреНрд╣реЗрдВ рд▓реЗрдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред Generic
рд╣реЗрд▓реНрдкрд░ рдХреЗ рдПрдХ рдЕрддрд┐рд░рд┐рдХреНрдд рддрд░реНрдХ рдХреЗ рд░реВрдк рдореЗрдВ рдЗрд╕ v
рдЙрдкрдпреЛрдЧ рдРрд╕реЗ рдЙрджрд╛рд╣рд░рдгреЛрдВ рдХреЗ рд╡рд┐рд╢рд┐рд╖реНрдЯ рдЕрдиреБрдХреНрд░рдо рдХреЛ рдирд┐рд░реНрдзрд╛рд░рд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХрд░реЗрдВ рдЬреЛ рдЕрдм v
рдХреЗ рдореВрд▓реНрдпреЛрдВ рд╕реЗ рдореЗрд▓ рдЦрд╛рддреЗ рд╣реИрдВред
рдЦреИрд░, рдпрд╣ рдмрд╛рдд рд╣реИ!
рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдкреЛрд╕реНрдЯ рдореЗрдВ, рд╣рдо рдЗрд╕ рджреГрд╖реНрдЯрд┐рдХреЛрдг рдХреЗ рдХреБрдЫ рд╕реБрд░реБрдЪрд┐рдкреВрд░реНрдг рдПрдХреНрд╕рдЯреЗрдВрд╢рди (рд╕рд╛рде рд╣реА рд╕реБрд░реБрдЪрд┐рдкреВрд░реНрдг рд╕реАрдорд╛рдПрдВ) рдХреЛ рджреЗрдЦреЗрдВрдЧреЗред
рдУрд╣, рдФрд░ рд╣рд╛рдБред рд╣рдорд╛рд░реЗ рд╕рд╛рдорд╛рдиреНрдпреАрдХрд░рдг рдХреЗ рдЕрдиреБрдХреНрд░рдо рдХреЛ рдЯреНрд░реИрдХ рдХрд░рдирд╛ рджрд┐рд▓рдЪрд╕реНрдк рд╣реИред
- рдПрдиреНрд╡ рдХреЗ рд╕рд╛рде рд╢реБрд░реВ
Env -> Foo
ред - рд╕рд╛рдорд╛рдиреНрдп рд░реВрдк рд╕реЗ рдкрд░реНрдпрд╛рдкреНрдд рдирд╣реАрдВ рд╣реИ,
Reader Env
рдореЛрдирдб рдореЗрдВ рд▓рдкреЗрдЯреЗрдВред - рд╕рд╛рдорд╛рдиреНрдп рд░реВрдк рд╕реЗ рдкрд░реНрдпрд╛рдкреНрдд рдирд╣реАрдВ рд╣реИ,
MonadReader Env m
рд╕рд╛рде рдлрд┐рд░ рд╕реЗ рд▓рд┐рдЦрдирд╛ред - рд╕рд╛рдорд╛рдиреНрдп рд░реВрдк рд╕реЗ рдкрд░реНрдпрд╛рдкреНрдд рдирд╣реАрдВ рд╣реИ,
MonadReader rm, HasEnv r
рдлрд┐рд░ рд╕реЗ MonadReader rm, HasEnv r
ред - рд╕рд╛рдорд╛рдиреНрдп рд░реВрдк рд╕реЗ рдкрд░реНрдпрд╛рдкреНрдд рдирд╣реАрдВ рд╣реИ,
MonadReader rm, Has Env r
рд▓рд┐рдЦреЗрдВ рдФрд░ рдЬреЗрдиреЗрд░рд┐рдХ рдЬреЛрдбрд╝реЗрдВ рддрд╛рдХрд┐ рдХрдВрдкрд╛рдЗрд▓рд░ рд╡рд╣рд╛рдВ рд╕рдм рдХреБрдЫ рдХрд░реЗред - рдЕрдм рдЖрджрд░реНрд╢ рд╣реИред