SlideShare a Scribd company logo
1 of 43
Download to read offline
Линзы
Комбинаторная манипуляция данными
Александр Гранин
graninas@gmail.com
1
data Contacts = Contacts {
contactEMail :: String,
contactSkype :: String }
data Person = Person {
personName :: String,
personSurname :: String,
personContacts :: Contacts }
data Account = CommonAccount {
accountPerson :: Person,
accountLogin :: String }
Person
Account
Contacts
contactEMail
contactSkype
2
3
updateAccountEMail account newMail = let
CommonAccount person login = account
Person name surname contacts = person
Contacts _ skype = contacts
newContacts = Contacts newMail skype
newPerson = Person name surname newContacts
newAccount = CommonAccount newPerson login
in newAccount
4
data Account =
CommonAccount {
accountPerson :: Person,
accountLogin :: String }
| PayedAccount {
accountPerson :: Person,
accountLogin :: String,
accountScores :: Int }
data Contacts = Contacts {
contactEMail :: String,
contactSkype :: String }
data Person = Person {
personName :: String,
personSurname :: String,
personContacts :: Contacts }
5
updateAccountEMail account newMail = let
CommonAccount person login = account
Person name surname contacts = person
Contacts _ skype = contacts
newContacts = Contacts newMail skype
newPerson = Person name surname newContacts
newAccount = CommonAccount newPerson login
in newAccount
?
6
updateAccountEMail account newMail = let
CommonAccount person login = account
Person name surname contacts = person
Contacts _ skype = contacts
newContacts = Contacts newMail skype
newPerson = Person name surname newContacts
newAccount = CommonAccount newPerson login
in newAccount
7
updateAccountEMail account newMail = case account of
CommonAccount p l = CommonAccount (updateP p newMail) l
PayedAccount p l s = PayedAccount (updateP p newMail) l s
where
updateP p mail = let
Person name surname contacts = p
Contacts _ skype = contacts
newContacts = Contacts mail skype
newPerson = Person name surname newContacts
in newPerson
8
updateAccountEMail account newMail = case account of
CommonAccount p l = CommonAccount (updateP p newMail) l
PayedAccount p l s = PayedAccount (updateP p newMail) l s
where
updateP p mail = let
Person name surname contacts = p
Contacts _ skype = contacts
newContacts = Contacts mail skype
newPerson = Person name surname newContacts
in newPerson
9
updateAccountEMail account newMail = let
person = accountPerson account
contacts = personContacts person
newContacts = contacts { contactEMail = newMail }
newPerson = person { personContacts = newContacts }
newAccount = account { accountPerson = newPerson }
in newAccount
getEMail contacts = contactEMail contacts
setEMail contacts mail = contacts { contactEMail = mail }
getContacts person = personContacts person
setContacts person contacts = person { personContacts = contacts }
getPerson account = accountPerson account
setPerson account person = account { accountPerson = person }
b = getB a
a = setB b a
10
getter :: A -> B
setter :: A -> B -> A
Линза = Геттер + Сеттер
lens :: (getter :: A -> B,
setter :: A -> B -> A)
eMailLens :: (Contacts -> String,
Contacts -> String -> Contacts)
eMailLens = (getEMail, setEMail)
where
getEMail contacts = contactEMail contacts
setEMail contacts mail = contacts {contactEMail = mail}
11
Комбинаторы view, set
view (getter, _) parent = getter parent
set (_, setter) parent value = setter parent value
> let contacts = Contacts "someone@null.ptr" "not_a_skype_account"
> view eMailLens contacts
"someone@null.ptr"
> set eMailLens contacts "dereference@null.ptr"
Contacts "dereference@null.ptr" "not_a_skype_account" 12
personLens = (getPerson, setPerson)
where
getPerson account = accountPerson account
setPerson account person = account {accountPerson = person}
contactLens = (getContacts, setContacts)
where
getContacts person = personContacts person
setContacts person contacts = person {personContacts = contacts}
13
Еще линзы
(getChild, setChild) . (getValue, setValue) = (getter, setter)
getter parent = getValue (getChild parent)
setter parent value = let
oldChild = getChild parent
newChild = setValue oldChild value
in setChild parent newChild
Композиция линз
14
Композиция линз - тоже линза
> let contacts = Contacts "someone@null.ptr" "not_a_skype_account"
> let person = Person “Some” “One” contacts
> view (contactLens . eMailLens) person
"someone@null.ptr"
> set (contactLens . eMailLens) person "dereference@null.ptr"
Person “Some” “One”
(Contacts "dereference@null.ptr" "not_a_skype_account") 15
> let contacts = Contacts "someone@null.ptr" "not_a_skype_account"
> let person = Person “Some” “One” contacts
> let account = PayedAccount person “login” 0
> view (eMailLens . contactLens . personLens) account
"someone@null.ptr"
> set (eMailLens . contactLens . personLens) account "42@nm.ru"
…………………………………………………………………………………
………………………………………………………………………………...
16
Композиция линз - тоже линза
Линзы в Haskell: библиотека lens
Автор - Edward Kmett
17
18
Fold Setter
Getter Traversal
Lens
Review
Prism
Iso Equality
data Contacts = Contacts {
_mail :: String,
_skype :: String }
data Person = Person {
_name :: String,
_surname :: String,
_contacts :: Contacts,
_skills :: [Skill] }
19
data Account =
CommonAccount {
_person :: Person,
_login :: String }
| PayedAccount {
_person :: Person,
_login :: String,
_scores :: Int }
data Skill = Cpp | CSharp | Haskell | Java | FSharp | Python
someoneContacts = Contacts "someone@null.ptr" "not_a_skype_account"
someOnePerson = Person "Some" "One" someoneContacts [Cpp, Haskell]
someOneAccount = PayedAccount someOnePerson "login" 0
grutContact = Contacts "i@am.grut" "grut"
grutPerson = Person "IAm" "Grut" grutContact [FSharp]
grutAccount = CommonAccount grutPerson "bla"
accounts = [someOneAccount, grutAccount]
20
makeLenses ''Contacts
makeLenses ''Person
makeLenses ''Account
Создание линз (Template Haskell)
name Person ===> String
surname Person ===> String
contacts Person ===> Contacts
person Account ===> Person
scores Account ===> Int
………. ……….. ……….....
21
Getters, Setters
22
Операторы view (^.), set (^~)
23
> let contacts’ = Contacts "someone@null.ptr" "not_a_skype_account"
> let person’ = Person “Some” “One” contacts’ [Cpp, Haskell ]
> let account’ = PayedAccount person’ “login” 0
> let mailLens = person . contacts . mail
> view mailLens account’
"someone@null.ptr"
> (set mailLens account’ "42@nm.ru") ^. mailLens
"42@nm.ru"
> let contacts’ = Contacts "someone@null.ptr" "not_a_skype_account"
> let person’ = Person “Some” “One” contacts’ [Cpp, Haskell ]
> let account’ = PayedAccount person’ “login” 0
let mailLens = person . contacts . mail
> (over mailLens (map toUpper) account') ^. mailLens
"SOMEONE@NULL.PTR"
Оператор over
24
Folds
25
someOnePerson = Person "Some" "One" someoneContacts [Cpp, Haskell]
grutPerson = Person "IAm" "Grut" grutContact [FSharp]
> view (folded . person . skills) accounts
[Cpp,Haskell,FSharp]
26
Оператор folded
someOnePerson = Person "Some" "One" someoneContacts [Cpp, Haskell]
grutPerson = Person "IAm" "Grut" grutContact [FSharp]
> view (folded . person . surname) accounts
“OneGrut”
Оператор folded
27
someOnePerson = Person "Some" "One" someoneContacts [Cpp, Haskell]
grutPerson = Person "IAm" "Grut" grutContact [FSharp]
> view (folded . person . contacts) accounts
No instance for (Data.Monoid.Monoid Contacts)
arising from a use of ‘folded’
In the first argument of ‘(.)’, namely ‘folded’
In the first argument of ‘view’, namely
‘(folded . person . contacts)’
In the expression: view (folded . person . contacts) accounts
28
Оператор folded
someOnePerson = Person "Some" "One" someoneContacts [Cpp, Haskell]
grutPerson = Person "IAm" "Grut" grutContact [FSharp]
> toListOf (folded . person . contacts) accounts
[ Contacts {_mail = "someone@null.ptr", _skype = "not_a_skype_account"}
, Contacts {_mail = "i@am.grut", _skype = "grut"}]
29
Оператор toListOf
someOnePerson = Person "Some" "One" someoneContacts [Cpp, Haskell]
grutPerson = Person "IAm" "Grut" grutContact [FSharp]
> toListOf (folded . person . surname) accounts
[“One”, “Grut”]
30
Оператор toListOf
someOnePerson = Person "Some" "One" someoneContacts [Cpp, Haskell]
grutPerson = Person "IAm" "Grut" grutContact [FSharp]
> let onlyGrut = filtered (acc -> acc ^. person.surname == "Grut")
> view olnyGrut accounts
No instance for (Data.Monoid.Monoid Account)
arising from a use of ‘onlyGrut’
In the first argument of ‘view’, namely ‘onlyGrut’
In the expression: view onlyGrut accounts
In an equation for ‘it’: it = view onlyGrut accounts
31
Оператор filtered
someOnePerson = Person "Some" "One" someoneContacts [Cpp, Haskell]
grutPerson = Person "IAm" "Grut" grutContact [FSharp]
> let onlyGrut = filtered (acc -> acc ^. person.surname == "Grut")
> toListOf olnyGrut accounts
Couldn't match type ‘[Account]’ with ‘Account’
Expected type: Getting (Data.Monoid.Endo [Account])
[Account] Account
Actual type: Optic' (->) (Const (Data.Monoid.Endo
[Account])) Account Account
In the first argument of ‘toListOf’, namely ‘onlyGrut’
32
Оператор filtered
someOnePerson = Person "Some" "One" someoneContacts [Cpp, Haskell]
grutPerson = Person "IAm" "Grut" grutContact [FSharp]
> let onlyGrut = filtered (acc -> acc ^. person.surname == "Grut")
> toListOf (folded . olnyGrut) accounts
[ CommonAccount {_person = Person {_name = "IAm", _surname = "Grut", _contacts = Contacts {_mail =
"i@am.grut", _skype = "grut"}, _skills = [FSharp]}, _login = "bla"}]
33
Операторы filtered + folded
someOnePerson = Person "Some" "One" someoneContacts [Cpp, Haskell]
grutPerson = Person "IAm" "Grut" grutContact [FSharp]
> let withN = filtered (acc -> ‘m’ `elem` acc ^. person.name)
> toListOf (folded . withN) accounts
[ PayedAccount {_person = Person {_name = "Some", _surname = "One", _contacts = Contacts {_mail =
"someone@null.ptr", _skype = "not_a_skype_account"}, _skills = [Cpp,Haskell]}, _login = "login", _scores =
0}
, CommonAccount {_person = Person {_name = "IAm", _surname = "Grut", _contacts = Contacts {_mail =
"i@am.grut", _skype = "grut"}, _skills = [FSharp]}, _login = "bla"}]
34
Еще пример filtered + folded
Prisms
35
> let result = Right grutPerson
> toListOf _Right result
[ Person {_name = "IAm", _surname = "Grut", _contacts = Contacts {_mail = "i@am.grut", _skype = "grut"},
_skills = [FSharp]} ]
> toListOf _Left result
[ ]
36
Операторы _Left, _Right
Комбинирование
37
> let result = Right grutPerson
> over (_Right . surname) (map toUpper) result
Right [ Person {_name = "IAm", _surname = "GRUT", _contacts = Contacts {_mail = "i@am.grut", _skype =
"grut"}, _skills = [FSharp]} ]
> over (_Left . surname) (map toUpper) result
Right [ Person {_name = "IAm", _surname = "Grut", _contacts = Contacts {_mail = "i@am.grut", _skype =
"grut"}, _skills = [FSharp]} ]
38
over + _Left, _Right
> let result = Right accounts
> let mailLens = person . contacts . mail
> over (_Right . traverse . mailLens) (map toUpper) result
Right
[ PayedAccount {_person = Person {_name = "Some", _surname = "One", _contacts = Contacts {_mail =
"SOMEONE@NULL.PTR", _skype = "not_a_skype_account"}, _skills = [Cpp,Haskell]}, _login = "login",
_scores = 0}
, CommonAccount {_person = Person {_name = "IAm", _surname = "Grut", _contacts = Contacts {_mail =
"I@AM.GRUT", _skype = "grut"}, _skills = [FSharp]}, _login = "bla"}]
39
over + traverse + _Right
#%%= **= //= //~ <<%@= <<.|.= <<^~ %= ...
#%%~ **~ <-= <#%= <<%@~ <<.|.~ <<||= %@= .=
#%= *= <-~ <#%~ <<%~ <<.~ <<||~ %@~ .>
#%~ *~ <. <#= <<&&= <<//= <<~ %~ .@=
#= += <.&.= <#~ <<&&~ <<//~ <>= & .@~
#~ +~ <.&.~ <%= <<**= <</>= <>~ &&= .|.=
%%= -= <.= <%@= <<**~ <</>~ <?= &&~ .|.~
%%@= -~ <.> <%@~ <<*= <<<.>= <?~ &~ .~
%%@~ .&.= <.>= <%~ <<*~ <<<.>~ <^= <.|.= <<-=
%%~ .&.~ <.>~ <&&= <<+= <<</>= <^^= <.|.~ <<-~
Тысячи операторов...
40
Сложные структуры данных
41
Zen
42
Спасибо за внимание!
Вопросы?
Александр Гранин
graninas@gmail.com
beginPresentation :: Presentation -> State Conference ()
beginPresentation title = currentPresentation .= title
listeners :: [Person] -> State Conference ()
listeners perss = setVisited (attendees . onlyListeners perss)
where
setVisited atts = do
title <- use currentPresentation
atts.visited %= (insert title)
onlyListeners :: Persons -> Traversal' [Attendee] Attendee
onlyListeners ls = traversed . filtered (att -> att ^. person `elem` ls) 43

More Related Content

What's hot

Penetration Testing with Improved Input Vector Identification
Penetration Testing with Improved Input Vector IdentificationPenetration Testing with Improved Input Vector Identification
Penetration Testing with Improved Input Vector IdentificationShauvik Roy Choudhary, Ph.D.
 
Conquering JSONB in PostgreSQL
Conquering JSONB in PostgreSQLConquering JSONB in PostgreSQL
Conquering JSONB in PostgreSQLInes Panker
 
MongoDB .local Munich 2019: Aggregation Pipeline Power++: How MongoDB 4.2 Pip...
MongoDB .local Munich 2019: Aggregation Pipeline Power++: How MongoDB 4.2 Pip...MongoDB .local Munich 2019: Aggregation Pipeline Power++: How MongoDB 4.2 Pip...
MongoDB .local Munich 2019: Aggregation Pipeline Power++: How MongoDB 4.2 Pip...MongoDB
 
The love child of Android and .NET: App development with Xamarin
The love child of Android and .NET: App development with XamarinThe love child of Android and .NET: App development with Xamarin
The love child of Android and .NET: App development with XamarinLorenz Cuno Klopfenstein
 
The Testing Games: Mocking, yay!
The Testing Games: Mocking, yay!The Testing Games: Mocking, yay!
The Testing Games: Mocking, yay!Donny Wals
 
INSERCION DE REGISTROS DESDE VISUAL.NET A UNA BD DE SQL SERVER
INSERCION DE REGISTROS DESDE VISUAL.NET A UNA BD DE SQL SERVERINSERCION DE REGISTROS DESDE VISUAL.NET A UNA BD DE SQL SERVER
INSERCION DE REGISTROS DESDE VISUAL.NET A UNA BD DE SQL SERVERDarwin Durand
 

What's hot (8)

Penetration Testing with Improved Input Vector Identification
Penetration Testing with Improved Input Vector IdentificationPenetration Testing with Improved Input Vector Identification
Penetration Testing with Improved Input Vector Identification
 
Conquering JSONB in PostgreSQL
Conquering JSONB in PostgreSQLConquering JSONB in PostgreSQL
Conquering JSONB in PostgreSQL
 
MongoDB .local Munich 2019: Aggregation Pipeline Power++: How MongoDB 4.2 Pip...
MongoDB .local Munich 2019: Aggregation Pipeline Power++: How MongoDB 4.2 Pip...MongoDB .local Munich 2019: Aggregation Pipeline Power++: How MongoDB 4.2 Pip...
MongoDB .local Munich 2019: Aggregation Pipeline Power++: How MongoDB 4.2 Pip...
 
The love child of Android and .NET: App development with Xamarin
The love child of Android and .NET: App development with XamarinThe love child of Android and .NET: App development with Xamarin
The love child of Android and .NET: App development with Xamarin
 
PureScript & Pux
PureScript & PuxPureScript & Pux
PureScript & Pux
 
Scala on Your Phone
Scala on Your PhoneScala on Your Phone
Scala on Your Phone
 
The Testing Games: Mocking, yay!
The Testing Games: Mocking, yay!The Testing Games: Mocking, yay!
The Testing Games: Mocking, yay!
 
INSERCION DE REGISTROS DESDE VISUAL.NET A UNA BD DE SQL SERVER
INSERCION DE REGISTROS DESDE VISUAL.NET A UNA BD DE SQL SERVERINSERCION DE REGISTROS DESDE VISUAL.NET A UNA BD DE SQL SERVER
INSERCION DE REGISTROS DESDE VISUAL.NET A UNA BD DE SQL SERVER
 

More from Alexander Granin

Concurrent applications with free monads and stm
Concurrent applications with free monads and stmConcurrent applications with free monads and stm
Concurrent applications with free monads and stmAlexander Granin
 
Hierarchical free monads and software design in fp
Hierarchical free monads and software design in fpHierarchical free monads and software design in fp
Hierarchical free monads and software design in fpAlexander Granin
 
Final tagless vs free monad
Final tagless vs free monadFinal tagless vs free monad
Final tagless vs free monadAlexander Granin
 
The present and the future of functional programming in c++
The present and the future of functional programming in c++The present and the future of functional programming in c++
The present and the future of functional programming in c++Alexander Granin
 
О разработке десктопных приложений / About desktop development
О разработке десктопных приложений / About desktop developmentО разработке десктопных приложений / About desktop development
О разработке десктопных приложений / About desktop developmentAlexander Granin
 
Принципы и практики разработки ПО 2 / Principles and practices of software de...
Принципы и практики разработки ПО 2 / Principles and practices of software de...Принципы и практики разработки ПО 2 / Principles and practices of software de...
Принципы и практики разработки ПО 2 / Principles and practices of software de...Alexander Granin
 
Принципы и практики разработки ПО / Principles and practices of software deve...
Принципы и практики разработки ПО / Principles and practices of software deve...Принципы и практики разработки ПО / Principles and practices of software deve...
Принципы и практики разработки ПО / Principles and practices of software deve...Alexander Granin
 
Закон Деметры / Demetra's law
Закон Деметры / Demetra's lawЗакон Деметры / Demetra's law
Закон Деметры / Demetra's lawAlexander Granin
 
Design of big applications in FP
Design of big applications in FPDesign of big applications in FP
Design of big applications in FPAlexander Granin
 
GitHub - зеркало разработчика
GitHub - зеркало разработчикаGitHub - зеркало разработчика
GitHub - зеркало разработчикаAlexander Granin
 
The Present and The Future of Functional Programming in C++
The Present and The Future of Functional Programming in C++The Present and The Future of Functional Programming in C++
The Present and The Future of Functional Programming in C++Alexander Granin
 
Functional programming in C++ LambdaNsk
Functional programming in C++ LambdaNskFunctional programming in C++ LambdaNsk
Functional programming in C++ LambdaNskAlexander Granin
 
Transition graph using free monads and existentials
Transition graph using free monads and existentialsTransition graph using free monads and existentials
Transition graph using free monads and existentialsAlexander Granin
 
Software transactional memory. pure functional approach
Software transactional memory. pure functional approachSoftware transactional memory. pure functional approach
Software transactional memory. pure functional approachAlexander Granin
 
Вы не понимаете ФП / You don't understand FP
Вы не понимаете ФП / You don't understand FPВы не понимаете ФП / You don't understand FP
Вы не понимаете ФП / You don't understand FPAlexander Granin
 
Functional "Life": parallel cellular automata and comonads
Functional "Life": parallel cellular automata and comonadsFunctional "Life": parallel cellular automata and comonads
Functional "Life": parallel cellular automata and comonadsAlexander Granin
 
Functional microscope - Lenses in C++
Functional microscope - Lenses in C++Functional microscope - Lenses in C++
Functional microscope - Lenses in C++Alexander Granin
 
Дизайн больших приложений в ФП
Дизайн больших приложений в ФПДизайн больших приложений в ФП
Дизайн больших приложений в ФПAlexander Granin
 
Линзы - комбинаторная манипуляция данными (Dev2Dev)
Линзы - комбинаторная манипуляция данными (Dev2Dev)Линзы - комбинаторная манипуляция данными (Dev2Dev)
Линзы - комбинаторная манипуляция данными (Dev2Dev)Alexander Granin
 

More from Alexander Granin (20)

Concurrent applications with free monads and stm
Concurrent applications with free monads and stmConcurrent applications with free monads and stm
Concurrent applications with free monads and stm
 
Hierarchical free monads and software design in fp
Hierarchical free monads and software design in fpHierarchical free monads and software design in fp
Hierarchical free monads and software design in fp
 
Final tagless vs free monad
Final tagless vs free monadFinal tagless vs free monad
Final tagless vs free monad
 
Monadic parsers in C++
Monadic parsers in C++Monadic parsers in C++
Monadic parsers in C++
 
The present and the future of functional programming in c++
The present and the future of functional programming in c++The present and the future of functional programming in c++
The present and the future of functional programming in c++
 
О разработке десктопных приложений / About desktop development
О разработке десктопных приложений / About desktop developmentО разработке десктопных приложений / About desktop development
О разработке десктопных приложений / About desktop development
 
Принципы и практики разработки ПО 2 / Principles and practices of software de...
Принципы и практики разработки ПО 2 / Principles and practices of software de...Принципы и практики разработки ПО 2 / Principles and practices of software de...
Принципы и практики разработки ПО 2 / Principles and practices of software de...
 
Принципы и практики разработки ПО / Principles and practices of software deve...
Принципы и практики разработки ПО / Principles and practices of software deve...Принципы и практики разработки ПО / Principles and practices of software deve...
Принципы и практики разработки ПО / Principles and practices of software deve...
 
Закон Деметры / Demetra's law
Закон Деметры / Demetra's lawЗакон Деметры / Demetra's law
Закон Деметры / Demetra's law
 
Design of big applications in FP
Design of big applications in FPDesign of big applications in FP
Design of big applications in FP
 
GitHub - зеркало разработчика
GitHub - зеркало разработчикаGitHub - зеркало разработчика
GitHub - зеркало разработчика
 
The Present and The Future of Functional Programming in C++
The Present and The Future of Functional Programming in C++The Present and The Future of Functional Programming in C++
The Present and The Future of Functional Programming in C++
 
Functional programming in C++ LambdaNsk
Functional programming in C++ LambdaNskFunctional programming in C++ LambdaNsk
Functional programming in C++ LambdaNsk
 
Transition graph using free monads and existentials
Transition graph using free monads and existentialsTransition graph using free monads and existentials
Transition graph using free monads and existentials
 
Software transactional memory. pure functional approach
Software transactional memory. pure functional approachSoftware transactional memory. pure functional approach
Software transactional memory. pure functional approach
 
Вы не понимаете ФП / You don't understand FP
Вы не понимаете ФП / You don't understand FPВы не понимаете ФП / You don't understand FP
Вы не понимаете ФП / You don't understand FP
 
Functional "Life": parallel cellular automata and comonads
Functional "Life": parallel cellular automata and comonadsFunctional "Life": parallel cellular automata and comonads
Functional "Life": parallel cellular automata and comonads
 
Functional microscope - Lenses in C++
Functional microscope - Lenses in C++Functional microscope - Lenses in C++
Functional microscope - Lenses in C++
 
Дизайн больших приложений в ФП
Дизайн больших приложений в ФПДизайн больших приложений в ФП
Дизайн больших приложений в ФП
 
Линзы - комбинаторная манипуляция данными (Dev2Dev)
Линзы - комбинаторная манипуляция данными (Dev2Dev)Линзы - комбинаторная манипуляция данными (Dev2Dev)
Линзы - комбинаторная манипуляция данными (Dev2Dev)
 

Recently uploaded

Artyushina_Guest lecture_YorkU CS May 2024.pptx
Artyushina_Guest lecture_YorkU CS May 2024.pptxArtyushina_Guest lecture_YorkU CS May 2024.pptx
Artyushina_Guest lecture_YorkU CS May 2024.pptxAnnaArtyushina1
 
%in Benoni+277-882-255-28 abortion pills for sale in Benoni
%in Benoni+277-882-255-28 abortion pills for sale in Benoni%in Benoni+277-882-255-28 abortion pills for sale in Benoni
%in Benoni+277-882-255-28 abortion pills for sale in Benonimasabamasaba
 
Love witchcraft +27768521739 Binding love spell in Sandy Springs, GA |psychic...
Love witchcraft +27768521739 Binding love spell in Sandy Springs, GA |psychic...Love witchcraft +27768521739 Binding love spell in Sandy Springs, GA |psychic...
Love witchcraft +27768521739 Binding love spell in Sandy Springs, GA |psychic...chiefasafspells
 
%in Hazyview+277-882-255-28 abortion pills for sale in Hazyview
%in Hazyview+277-882-255-28 abortion pills for sale in Hazyview%in Hazyview+277-882-255-28 abortion pills for sale in Hazyview
%in Hazyview+277-882-255-28 abortion pills for sale in Hazyviewmasabamasaba
 
Payment Gateway Testing Simplified_ A Step-by-Step Guide for Beginners.pdf
Payment Gateway Testing Simplified_ A Step-by-Step Guide for Beginners.pdfPayment Gateway Testing Simplified_ A Step-by-Step Guide for Beginners.pdf
Payment Gateway Testing Simplified_ A Step-by-Step Guide for Beginners.pdfkalichargn70th171
 
8257 interfacing 2 in microprocessor for btech students
8257 interfacing 2 in microprocessor for btech students8257 interfacing 2 in microprocessor for btech students
8257 interfacing 2 in microprocessor for btech studentsHimanshiGarg82
 
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...Health
 
Large-scale Logging Made Easy: Meetup at Deutsche Bank 2024
Large-scale Logging Made Easy: Meetup at Deutsche Bank 2024Large-scale Logging Made Easy: Meetup at Deutsche Bank 2024
Large-scale Logging Made Easy: Meetup at Deutsche Bank 2024VictoriaMetrics
 
WSO2CON 2024 - Cloud Native Middleware: Domain-Driven Design, Cell-Based Arch...
WSO2CON 2024 - Cloud Native Middleware: Domain-Driven Design, Cell-Based Arch...WSO2CON 2024 - Cloud Native Middleware: Domain-Driven Design, Cell-Based Arch...
WSO2CON 2024 - Cloud Native Middleware: Domain-Driven Design, Cell-Based Arch...WSO2
 
WSO2Con2024 - From Code To Cloud: Fast Track Your Cloud Native Journey with C...
WSO2Con2024 - From Code To Cloud: Fast Track Your Cloud Native Journey with C...WSO2Con2024 - From Code To Cloud: Fast Track Your Cloud Native Journey with C...
WSO2Con2024 - From Code To Cloud: Fast Track Your Cloud Native Journey with C...WSO2
 
%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...
%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...
%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...masabamasaba
 
AI & Machine Learning Presentation Template
AI & Machine Learning Presentation TemplateAI & Machine Learning Presentation Template
AI & Machine Learning Presentation TemplatePresentation.STUDIO
 
%in Rustenburg+277-882-255-28 abortion pills for sale in Rustenburg
%in Rustenburg+277-882-255-28 abortion pills for sale in Rustenburg%in Rustenburg+277-882-255-28 abortion pills for sale in Rustenburg
%in Rustenburg+277-882-255-28 abortion pills for sale in Rustenburgmasabamasaba
 
%in kaalfontein+277-882-255-28 abortion pills for sale in kaalfontein
%in kaalfontein+277-882-255-28 abortion pills for sale in kaalfontein%in kaalfontein+277-882-255-28 abortion pills for sale in kaalfontein
%in kaalfontein+277-882-255-28 abortion pills for sale in kaalfonteinmasabamasaba
 
%in tembisa+277-882-255-28 abortion pills for sale in tembisa
%in tembisa+277-882-255-28 abortion pills for sale in tembisa%in tembisa+277-882-255-28 abortion pills for sale in tembisa
%in tembisa+277-882-255-28 abortion pills for sale in tembisamasabamasaba
 
Announcing Codolex 2.0 from GDK Software
Announcing Codolex 2.0 from GDK SoftwareAnnouncing Codolex 2.0 from GDK Software
Announcing Codolex 2.0 from GDK SoftwareJim McKeeth
 
WSO2CON 2024 - Building the API First Enterprise – Running an API Program, fr...
WSO2CON 2024 - Building the API First Enterprise – Running an API Program, fr...WSO2CON 2024 - Building the API First Enterprise – Running an API Program, fr...
WSO2CON 2024 - Building the API First Enterprise – Running an API Program, fr...WSO2
 
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...panagenda
 
%in Bahrain+277-882-255-28 abortion pills for sale in Bahrain
%in Bahrain+277-882-255-28 abortion pills for sale in Bahrain%in Bahrain+277-882-255-28 abortion pills for sale in Bahrain
%in Bahrain+277-882-255-28 abortion pills for sale in Bahrainmasabamasaba
 
WSO2CON 2024 - Does Open Source Still Matter?
WSO2CON 2024 - Does Open Source Still Matter?WSO2CON 2024 - Does Open Source Still Matter?
WSO2CON 2024 - Does Open Source Still Matter?WSO2
 

Recently uploaded (20)

Artyushina_Guest lecture_YorkU CS May 2024.pptx
Artyushina_Guest lecture_YorkU CS May 2024.pptxArtyushina_Guest lecture_YorkU CS May 2024.pptx
Artyushina_Guest lecture_YorkU CS May 2024.pptx
 
%in Benoni+277-882-255-28 abortion pills for sale in Benoni
%in Benoni+277-882-255-28 abortion pills for sale in Benoni%in Benoni+277-882-255-28 abortion pills for sale in Benoni
%in Benoni+277-882-255-28 abortion pills for sale in Benoni
 
Love witchcraft +27768521739 Binding love spell in Sandy Springs, GA |psychic...
Love witchcraft +27768521739 Binding love spell in Sandy Springs, GA |psychic...Love witchcraft +27768521739 Binding love spell in Sandy Springs, GA |psychic...
Love witchcraft +27768521739 Binding love spell in Sandy Springs, GA |psychic...
 
%in Hazyview+277-882-255-28 abortion pills for sale in Hazyview
%in Hazyview+277-882-255-28 abortion pills for sale in Hazyview%in Hazyview+277-882-255-28 abortion pills for sale in Hazyview
%in Hazyview+277-882-255-28 abortion pills for sale in Hazyview
 
Payment Gateway Testing Simplified_ A Step-by-Step Guide for Beginners.pdf
Payment Gateway Testing Simplified_ A Step-by-Step Guide for Beginners.pdfPayment Gateway Testing Simplified_ A Step-by-Step Guide for Beginners.pdf
Payment Gateway Testing Simplified_ A Step-by-Step Guide for Beginners.pdf
 
8257 interfacing 2 in microprocessor for btech students
8257 interfacing 2 in microprocessor for btech students8257 interfacing 2 in microprocessor for btech students
8257 interfacing 2 in microprocessor for btech students
 
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
 
Large-scale Logging Made Easy: Meetup at Deutsche Bank 2024
Large-scale Logging Made Easy: Meetup at Deutsche Bank 2024Large-scale Logging Made Easy: Meetup at Deutsche Bank 2024
Large-scale Logging Made Easy: Meetup at Deutsche Bank 2024
 
WSO2CON 2024 - Cloud Native Middleware: Domain-Driven Design, Cell-Based Arch...
WSO2CON 2024 - Cloud Native Middleware: Domain-Driven Design, Cell-Based Arch...WSO2CON 2024 - Cloud Native Middleware: Domain-Driven Design, Cell-Based Arch...
WSO2CON 2024 - Cloud Native Middleware: Domain-Driven Design, Cell-Based Arch...
 
WSO2Con2024 - From Code To Cloud: Fast Track Your Cloud Native Journey with C...
WSO2Con2024 - From Code To Cloud: Fast Track Your Cloud Native Journey with C...WSO2Con2024 - From Code To Cloud: Fast Track Your Cloud Native Journey with C...
WSO2Con2024 - From Code To Cloud: Fast Track Your Cloud Native Journey with C...
 
%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...
%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...
%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...
 
AI & Machine Learning Presentation Template
AI & Machine Learning Presentation TemplateAI & Machine Learning Presentation Template
AI & Machine Learning Presentation Template
 
%in Rustenburg+277-882-255-28 abortion pills for sale in Rustenburg
%in Rustenburg+277-882-255-28 abortion pills for sale in Rustenburg%in Rustenburg+277-882-255-28 abortion pills for sale in Rustenburg
%in Rustenburg+277-882-255-28 abortion pills for sale in Rustenburg
 
%in kaalfontein+277-882-255-28 abortion pills for sale in kaalfontein
%in kaalfontein+277-882-255-28 abortion pills for sale in kaalfontein%in kaalfontein+277-882-255-28 abortion pills for sale in kaalfontein
%in kaalfontein+277-882-255-28 abortion pills for sale in kaalfontein
 
%in tembisa+277-882-255-28 abortion pills for sale in tembisa
%in tembisa+277-882-255-28 abortion pills for sale in tembisa%in tembisa+277-882-255-28 abortion pills for sale in tembisa
%in tembisa+277-882-255-28 abortion pills for sale in tembisa
 
Announcing Codolex 2.0 from GDK Software
Announcing Codolex 2.0 from GDK SoftwareAnnouncing Codolex 2.0 from GDK Software
Announcing Codolex 2.0 from GDK Software
 
WSO2CON 2024 - Building the API First Enterprise – Running an API Program, fr...
WSO2CON 2024 - Building the API First Enterprise – Running an API Program, fr...WSO2CON 2024 - Building the API First Enterprise – Running an API Program, fr...
WSO2CON 2024 - Building the API First Enterprise – Running an API Program, fr...
 
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
 
%in Bahrain+277-882-255-28 abortion pills for sale in Bahrain
%in Bahrain+277-882-255-28 abortion pills for sale in Bahrain%in Bahrain+277-882-255-28 abortion pills for sale in Bahrain
%in Bahrain+277-882-255-28 abortion pills for sale in Bahrain
 
WSO2CON 2024 - Does Open Source Still Matter?
WSO2CON 2024 - Does Open Source Still Matter?WSO2CON 2024 - Does Open Source Still Matter?
WSO2CON 2024 - Does Open Source Still Matter?
 

Линзы - комбинаторная манипуляция данными

  • 2. data Contacts = Contacts { contactEMail :: String, contactSkype :: String } data Person = Person { personName :: String, personSurname :: String, personContacts :: Contacts } data Account = CommonAccount { accountPerson :: Person, accountLogin :: String } Person Account Contacts contactEMail contactSkype 2
  • 3. 3 updateAccountEMail account newMail = let CommonAccount person login = account Person name surname contacts = person Contacts _ skype = contacts newContacts = Contacts newMail skype newPerson = Person name surname newContacts newAccount = CommonAccount newPerson login in newAccount
  • 4. 4 data Account = CommonAccount { accountPerson :: Person, accountLogin :: String } | PayedAccount { accountPerson :: Person, accountLogin :: String, accountScores :: Int } data Contacts = Contacts { contactEMail :: String, contactSkype :: String } data Person = Person { personName :: String, personSurname :: String, personContacts :: Contacts }
  • 5. 5 updateAccountEMail account newMail = let CommonAccount person login = account Person name surname contacts = person Contacts _ skype = contacts newContacts = Contacts newMail skype newPerson = Person name surname newContacts newAccount = CommonAccount newPerson login in newAccount ?
  • 6. 6 updateAccountEMail account newMail = let CommonAccount person login = account Person name surname contacts = person Contacts _ skype = contacts newContacts = Contacts newMail skype newPerson = Person name surname newContacts newAccount = CommonAccount newPerson login in newAccount
  • 7. 7 updateAccountEMail account newMail = case account of CommonAccount p l = CommonAccount (updateP p newMail) l PayedAccount p l s = PayedAccount (updateP p newMail) l s where updateP p mail = let Person name surname contacts = p Contacts _ skype = contacts newContacts = Contacts mail skype newPerson = Person name surname newContacts in newPerson
  • 8. 8 updateAccountEMail account newMail = case account of CommonAccount p l = CommonAccount (updateP p newMail) l PayedAccount p l s = PayedAccount (updateP p newMail) l s where updateP p mail = let Person name surname contacts = p Contacts _ skype = contacts newContacts = Contacts mail skype newPerson = Person name surname newContacts in newPerson
  • 9. 9 updateAccountEMail account newMail = let person = accountPerson account contacts = personContacts person newContacts = contacts { contactEMail = newMail } newPerson = person { personContacts = newContacts } newAccount = account { accountPerson = newPerson } in newAccount
  • 10. getEMail contacts = contactEMail contacts setEMail contacts mail = contacts { contactEMail = mail } getContacts person = personContacts person setContacts person contacts = person { personContacts = contacts } getPerson account = accountPerson account setPerson account person = account { accountPerson = person } b = getB a a = setB b a 10 getter :: A -> B setter :: A -> B -> A
  • 11. Линза = Геттер + Сеттер lens :: (getter :: A -> B, setter :: A -> B -> A) eMailLens :: (Contacts -> String, Contacts -> String -> Contacts) eMailLens = (getEMail, setEMail) where getEMail contacts = contactEMail contacts setEMail contacts mail = contacts {contactEMail = mail} 11
  • 12. Комбинаторы view, set view (getter, _) parent = getter parent set (_, setter) parent value = setter parent value > let contacts = Contacts "someone@null.ptr" "not_a_skype_account" > view eMailLens contacts "someone@null.ptr" > set eMailLens contacts "dereference@null.ptr" Contacts "dereference@null.ptr" "not_a_skype_account" 12
  • 13. personLens = (getPerson, setPerson) where getPerson account = accountPerson account setPerson account person = account {accountPerson = person} contactLens = (getContacts, setContacts) where getContacts person = personContacts person setContacts person contacts = person {personContacts = contacts} 13 Еще линзы
  • 14. (getChild, setChild) . (getValue, setValue) = (getter, setter) getter parent = getValue (getChild parent) setter parent value = let oldChild = getChild parent newChild = setValue oldChild value in setChild parent newChild Композиция линз 14
  • 15. Композиция линз - тоже линза > let contacts = Contacts "someone@null.ptr" "not_a_skype_account" > let person = Person “Some” “One” contacts > view (contactLens . eMailLens) person "someone@null.ptr" > set (contactLens . eMailLens) person "dereference@null.ptr" Person “Some” “One” (Contacts "dereference@null.ptr" "not_a_skype_account") 15
  • 16. > let contacts = Contacts "someone@null.ptr" "not_a_skype_account" > let person = Person “Some” “One” contacts > let account = PayedAccount person “login” 0 > view (eMailLens . contactLens . personLens) account "someone@null.ptr" > set (eMailLens . contactLens . personLens) account "42@nm.ru" ………………………………………………………………………………… ………………………………………………………………………………... 16 Композиция линз - тоже линза
  • 17. Линзы в Haskell: библиотека lens Автор - Edward Kmett 17
  • 19. data Contacts = Contacts { _mail :: String, _skype :: String } data Person = Person { _name :: String, _surname :: String, _contacts :: Contacts, _skills :: [Skill] } 19 data Account = CommonAccount { _person :: Person, _login :: String } | PayedAccount { _person :: Person, _login :: String, _scores :: Int } data Skill = Cpp | CSharp | Haskell | Java | FSharp | Python
  • 20. someoneContacts = Contacts "someone@null.ptr" "not_a_skype_account" someOnePerson = Person "Some" "One" someoneContacts [Cpp, Haskell] someOneAccount = PayedAccount someOnePerson "login" 0 grutContact = Contacts "i@am.grut" "grut" grutPerson = Person "IAm" "Grut" grutContact [FSharp] grutAccount = CommonAccount grutPerson "bla" accounts = [someOneAccount, grutAccount] 20
  • 21. makeLenses ''Contacts makeLenses ''Person makeLenses ''Account Создание линз (Template Haskell) name Person ===> String surname Person ===> String contacts Person ===> Contacts person Account ===> Person scores Account ===> Int ………. ……….. ………..... 21
  • 23. Операторы view (^.), set (^~) 23 > let contacts’ = Contacts "someone@null.ptr" "not_a_skype_account" > let person’ = Person “Some” “One” contacts’ [Cpp, Haskell ] > let account’ = PayedAccount person’ “login” 0 > let mailLens = person . contacts . mail > view mailLens account’ "someone@null.ptr" > (set mailLens account’ "42@nm.ru") ^. mailLens "42@nm.ru"
  • 24. > let contacts’ = Contacts "someone@null.ptr" "not_a_skype_account" > let person’ = Person “Some” “One” contacts’ [Cpp, Haskell ] > let account’ = PayedAccount person’ “login” 0 let mailLens = person . contacts . mail > (over mailLens (map toUpper) account') ^. mailLens "SOMEONE@NULL.PTR" Оператор over 24
  • 26. someOnePerson = Person "Some" "One" someoneContacts [Cpp, Haskell] grutPerson = Person "IAm" "Grut" grutContact [FSharp] > view (folded . person . skills) accounts [Cpp,Haskell,FSharp] 26 Оператор folded
  • 27. someOnePerson = Person "Some" "One" someoneContacts [Cpp, Haskell] grutPerson = Person "IAm" "Grut" grutContact [FSharp] > view (folded . person . surname) accounts “OneGrut” Оператор folded 27
  • 28. someOnePerson = Person "Some" "One" someoneContacts [Cpp, Haskell] grutPerson = Person "IAm" "Grut" grutContact [FSharp] > view (folded . person . contacts) accounts No instance for (Data.Monoid.Monoid Contacts) arising from a use of ‘folded’ In the first argument of ‘(.)’, namely ‘folded’ In the first argument of ‘view’, namely ‘(folded . person . contacts)’ In the expression: view (folded . person . contacts) accounts 28 Оператор folded
  • 29. someOnePerson = Person "Some" "One" someoneContacts [Cpp, Haskell] grutPerson = Person "IAm" "Grut" grutContact [FSharp] > toListOf (folded . person . contacts) accounts [ Contacts {_mail = "someone@null.ptr", _skype = "not_a_skype_account"} , Contacts {_mail = "i@am.grut", _skype = "grut"}] 29 Оператор toListOf
  • 30. someOnePerson = Person "Some" "One" someoneContacts [Cpp, Haskell] grutPerson = Person "IAm" "Grut" grutContact [FSharp] > toListOf (folded . person . surname) accounts [“One”, “Grut”] 30 Оператор toListOf
  • 31. someOnePerson = Person "Some" "One" someoneContacts [Cpp, Haskell] grutPerson = Person "IAm" "Grut" grutContact [FSharp] > let onlyGrut = filtered (acc -> acc ^. person.surname == "Grut") > view olnyGrut accounts No instance for (Data.Monoid.Monoid Account) arising from a use of ‘onlyGrut’ In the first argument of ‘view’, namely ‘onlyGrut’ In the expression: view onlyGrut accounts In an equation for ‘it’: it = view onlyGrut accounts 31 Оператор filtered
  • 32. someOnePerson = Person "Some" "One" someoneContacts [Cpp, Haskell] grutPerson = Person "IAm" "Grut" grutContact [FSharp] > let onlyGrut = filtered (acc -> acc ^. person.surname == "Grut") > toListOf olnyGrut accounts Couldn't match type ‘[Account]’ with ‘Account’ Expected type: Getting (Data.Monoid.Endo [Account]) [Account] Account Actual type: Optic' (->) (Const (Data.Monoid.Endo [Account])) Account Account In the first argument of ‘toListOf’, namely ‘onlyGrut’ 32 Оператор filtered
  • 33. someOnePerson = Person "Some" "One" someoneContacts [Cpp, Haskell] grutPerson = Person "IAm" "Grut" grutContact [FSharp] > let onlyGrut = filtered (acc -> acc ^. person.surname == "Grut") > toListOf (folded . olnyGrut) accounts [ CommonAccount {_person = Person {_name = "IAm", _surname = "Grut", _contacts = Contacts {_mail = "i@am.grut", _skype = "grut"}, _skills = [FSharp]}, _login = "bla"}] 33 Операторы filtered + folded
  • 34. someOnePerson = Person "Some" "One" someoneContacts [Cpp, Haskell] grutPerson = Person "IAm" "Grut" grutContact [FSharp] > let withN = filtered (acc -> ‘m’ `elem` acc ^. person.name) > toListOf (folded . withN) accounts [ PayedAccount {_person = Person {_name = "Some", _surname = "One", _contacts = Contacts {_mail = "someone@null.ptr", _skype = "not_a_skype_account"}, _skills = [Cpp,Haskell]}, _login = "login", _scores = 0} , CommonAccount {_person = Person {_name = "IAm", _surname = "Grut", _contacts = Contacts {_mail = "i@am.grut", _skype = "grut"}, _skills = [FSharp]}, _login = "bla"}] 34 Еще пример filtered + folded
  • 36. > let result = Right grutPerson > toListOf _Right result [ Person {_name = "IAm", _surname = "Grut", _contacts = Contacts {_mail = "i@am.grut", _skype = "grut"}, _skills = [FSharp]} ] > toListOf _Left result [ ] 36 Операторы _Left, _Right
  • 38. > let result = Right grutPerson > over (_Right . surname) (map toUpper) result Right [ Person {_name = "IAm", _surname = "GRUT", _contacts = Contacts {_mail = "i@am.grut", _skype = "grut"}, _skills = [FSharp]} ] > over (_Left . surname) (map toUpper) result Right [ Person {_name = "IAm", _surname = "Grut", _contacts = Contacts {_mail = "i@am.grut", _skype = "grut"}, _skills = [FSharp]} ] 38 over + _Left, _Right
  • 39. > let result = Right accounts > let mailLens = person . contacts . mail > over (_Right . traverse . mailLens) (map toUpper) result Right [ PayedAccount {_person = Person {_name = "Some", _surname = "One", _contacts = Contacts {_mail = "SOMEONE@NULL.PTR", _skype = "not_a_skype_account"}, _skills = [Cpp,Haskell]}, _login = "login", _scores = 0} , CommonAccount {_person = Person {_name = "IAm", _surname = "Grut", _contacts = Contacts {_mail = "I@AM.GRUT", _skype = "grut"}, _skills = [FSharp]}, _login = "bla"}] 39 over + traverse + _Right
  • 40. #%%= **= //= //~ <<%@= <<.|.= <<^~ %= ... #%%~ **~ <-= <#%= <<%@~ <<.|.~ <<||= %@= .= #%= *= <-~ <#%~ <<%~ <<.~ <<||~ %@~ .> #%~ *~ <. <#= <<&&= <<//= <<~ %~ .@= #= += <.&.= <#~ <<&&~ <<//~ <>= & .@~ #~ +~ <.&.~ <%= <<**= <</>= <>~ &&= .|.= %%= -= <.= <%@= <<**~ <</>~ <?= &&~ .|.~ %%@= -~ <.> <%@~ <<*= <<<.>= <?~ &~ .~ %%@~ .&.= <.>= <%~ <<*~ <<<.>~ <^= <.|.= <<-= %%~ .&.~ <.>~ <&&= <<+= <<</>= <^^= <.|.~ <<-~ Тысячи операторов... 40
  • 43. beginPresentation :: Presentation -> State Conference () beginPresentation title = currentPresentation .= title listeners :: [Person] -> State Conference () listeners perss = setVisited (attendees . onlyListeners perss) where setVisited atts = do title <- use currentPresentation atts.visited %= (insert title) onlyListeners :: Persons -> Traversal' [Attendee] Attendee onlyListeners ls = traversed . filtered (att -> att ^. person `elem` ls) 43