SlideShare a Scribd company logo
Линзы
Комбинаторная манипуляция данными
Александр Гранин
graninas@gmail.com
1
О себе
● Haskell, C++, немного C#
● Организатор сообщества LambdaNsk
● Доклады:
o Haskell. DevDay@2GIS
o ФП вчера и сегодня. TechTalks@NSU
o Функционально-декларативный дизайн на С++
o Идиоматичный ФП-код. LambdaNsk
2
● Очень кратко о ФП
● Линзы в Haskell
● Сценарии с использованием линз
● Линзы в других языках
План доклада
3
Функциональное программирование
● Функции высших порядков
● Лямбды
● Замыкания
● Иммутабельность
● Рекурсия
4
Функциональное программирование
● Функции высших порядков
● Лямбды
● Замыкания
● Иммутабельность
● Рекурсия
● Математические абстракции
5
data Credentials = Credentials {
credentialsLogin :: String,
credentialsPassword :: String }
Credentials
Login
Password
6
Простой алгебраический тип данных
updatePassword credentials newPassword = let
(Credentials login _) = credentials
in (Credentials login newPassword)
updatePassword2 credentials newPassword =
credentials { credentialsPassword = newPassword }
Изменение значения простого АТД
7
data Credentials = Credentials {
credentialsLogin :: String,
credentialsPassword :: String }
Credentials
Login
Password
data Credentials = Credentials {
credentialsLogin :: String,
credentialsPassword :: String }
data Person = Person {
personName :: String,
personSurname :: String,
personCredentials :: Credentials }
8
Более сложный АТД
Person
Credentials
Login
Password
Credentials
Login
Password
Credentials
Name
Surname
updatePersonPassword person newPass = let
credentials = personCredentials person
newCreds = credentials { credentialsPassword = newPass }
newPerson = person { personCredentials = newCreds }
in newPerson
9
Изменение более сложного АТД
data Credentials = Credentials {
credentialsLogin :: String,
credentialsPassword :: String }
data Person = Person {
personName :: String,
personSurname :: String,
personCredentials :: Credentials }
data Subscriber = Subscriber {
subscriberPerson :: Person,
subscriberTariffId :: Int }
Person
Subscriber
Credentials
Login
Password
10
А что, если?..
updateSubscriberPassword subscriber newPass = let
person = subscriberPerson subscriber
credentials = personCredentials person
newCreds = credentials { credentialsPassword = newPass }
newPerson = person { personCredentials = newCreds }
newSubscriber = subscriber { subscriberPerson = newPerson }
in newSubscriber
11
updateSubscriberPassword subscriber newPass = let
person = subscriberPerson subscriber
credentials = personCredentials person
newCreds = credentials { credentialsPassword = newPass }
newPerson = person { personCredentials = newCreds }
newSubscriber = subscriber { subscriberPerson = newPerson }
in newSubscriber
Getters
Setters
12
person = subscriberPerson subscriber
newSubscriber = subscriber { subscriberPerson = person }
credentials = personCredentials person
newPerson = person { personCredentials = credentials }
password = credentialsPassword credentials
newCreds = credentials { credentialsPassword = password }
b = getB a
a = setB b a
13
getPerson subscriber = subscriberPerson subscriber
setPerson subscriber person = subscriber { subscriberPerson = person }
getCredentials person = personCredentials person
setCredentials person creds = person { personCredentials = creds }
getPassword creds = credentialsPassword creds
setPassword creds pass = creds { credentialsPassword = pass }
b = getB a
a = setB b a
14
getter :: A -> B
setter :: A -> B -> A
Линза = Геттер + Сеттер
lens :: (getter :: A -> B,
setter :: A -> B -> A)
passwordLens :: (Credentials -> String,
Credentials -> String -> Credentials)
passwordLens = (getPass, setPass)
where
getPass creds = credentialsPassword creds
setPass creds newPass = creds {credentialsPassword = newPass}
15
Простые операторы view и set
view (getter, _) parent = getter parent
set (_, setter) parent value = setter parent value
> let myCredentials = Credentials "login" "pass"
> view passwordLens myCredentials
"pass"
> set passwordLens myCredentials "qwerty"
Credentials "login" "qwerty"
16
credentialsLens = (getCreds, setCreds)
where
getCreds person = personCredentials person
setCreds person newCreds = person {personCredentials = newCreds}
personLens = (getPerson, setPerson)
where
getPerson subscr = subscriberPerson subscr
setPerson subscr newPers = subscr {subscriberPerson = newPers}
Еще линзы
17
(getChild, setChild) . (getValue, setValue) = (getter, setter)
where
getter parent = getValue (getChild parent)
setter parent value = let
oldChild = getChild parent
newChild = setValue oldChild value
in setChild parent newChild
Линза . линза = линза
18
Композиция!
myCredentials = Credentials "login" "pass"
mePerson = Person "Alex" "Granin" myCredentials
> view (credentialsLens . passwordLens) mePerson
“pass”
> set (credentialsLens . passwordLens) mePerson “qwerty”
Person "Alex" "Granin" (Credentials "login" "qwerty")
Линза . линза = линза
19
Линзы в Haskell: библиотека lens
Автор - Edward Kmett
20
data ContactType = VK | FB | Twitter | Email
data Skill = Cpp | CSharp | Haskell | Java | FSharp | Python
data Person = Person {
_name :: String,
_surname :: String,
_contacts :: [(ContactType, String)],
_skills :: [Skill]
}
АТД Person
Person
Name
Surname
Contacts
Skills
21
type Presentation = String
data Attendee =
Speaker {
_person :: Person,
_visited :: [Presentation],
_presentationTitle :: String }
| Attendee {
_person :: Person,
_visited :: [Presentation] }
АТД Attendee
Attendee
Person
Name
Surname
Contacts
Skills
22
-- Template Haskell rocks:
makeLenses ''Person
makeLenses ''Attendee
Создание линз
_name name Person ===>
String
_surname surname Person ===>
String
_contacts contacts Person ===>
Contacts
_person person Attendee ===>
Person
_visited visited Attendee ===> 23
pete = Person "Pete" "Howard" [(FB, "pete")] [Java, Python]
peteAttendee = Attendee pete []
> _name (_person peteAttendee) -- Manual
“Pete”
> view (person.name) peteAttendee -- With lenses
“Pete”
> peteAttendee ^. (person.name) -- The same
“Pete”
Оператор view (^.)
24
> peteAttendee ^. person.skills
[Java,Python]
> itoList (peteAttendee ^. person.skills)
[(0,Java),(1,Python)]
> (itoList (peteAttendee ^. person.skills)) ^.. ix 1
[(1,Python)]
Операторы itoList, (^..) и ix
25
setAttendeeName att n = case att of
Speaker pers visit theme -> Speaker (setName pers) visit theme
Attendee pers visit -> Attendee (setName pers) visit
where
setName (Person _ s cts skls) = Person n s cts skls
setAttendeeName’ att n = set (person.name) "Jack" att
Оператор set
26
addContact att contact = case att of
Speaker pers visit theme -> Speaker (appendContact pers) visit theme
Attendee pers visit -> Attendee (appendContact pers) visit
where
appendContact (Person n s cts skls) = Person n s (contact : cts) skls
addContact' att contact =
over (person . contacts) (insert contact) att
Оператор over
27
#%%= **= //= //~ <<%@= <<.|.= <<^~ %= ...
#%%~ **~ <-= <#%= <<%@~ <<.|.~ <<||= %@= .=
#%= *= <-~ <#%~ <<%~ <<.~ <<||~ %@~ .>
#%~ *~ <. <#= <<&&= <<//= <<~ %~ .@=
#= += <.&.= <#~ <<&&~ <<//~ <>= & .@~
#~ +~ <.&.~ <%= <<**= <</>= <>~ &&= .|.=
%%= -= <.= <%@= <<**~ <</>~ <?= &&~ .|.~
%%@= -~ <.> <%@~ <<*= <<<.>= <?~ &~ .~
%%@~ .&.= <.>= <%~ <<*~ <<<.>~ <^= <.|.= <<-=
%%~ .&.~ <.>~ <&&= <<+= <<</>= <^^= <.|.~ <<-~
Тысячи их...
Zen 28
Сценарии с использованием линз
29
data Conference = Conference {
_attendees :: [Attendee],
_currentPresentation :: Presentation,
_conferenceTweets ::
[(Presentation, Person, String)]
}
АТД Conference
Attendee
Person
Conference
currentPresentation
conferenceTweets
30
pete = Person "Pete" "Howard" [facebook "pete"] [Java]
jakob = Person "Jakob" "Brown" [twitter "jab"] [Java, CSharp]
lana = Person "Lana" "Dell" [] [FSharp]
alex = Person "Alexander" "Granin" [vk "graninas"] [Haskell]
guru = Person "Real" "Guru" [] [Cpp, Java, CSharp, Haskell]
confAttendees = [ attendee pete, attendee jakob, attendee lana,
speaker alex "Lenses",
speaker guru “Multilanguage projects”]
conference = Conference confAttendees "" []
31
conferenceScenario :: State Conference ()
conferenceScenario = do
alex `tweeted` "Rush hour, sorry. #dev2dev"
beginPresentation "Multilanguage projects"
setListeners [pete, jakob, lana]
jakob `tweeted` "Great talk! #dev2dev"
lana `tweeted` "So technical. #dev2dev"
pete `tweeted` "#MLP 222 coming soon."
32
Сценарий “Конференция”
tweeted :: Person -> Msg -> State Conference ()
tweeted pers msg = if "#dev2dev" `isInfixOf` msg
then writeTweet pers msg
else return ()
writeTweet :: Person -> Msg -> State Conference ()
writeTweet pers msg = do
presentationName <- use currentPresentation
conferenceTweets %= insert (presentationName, pers, msg)
33
Сценарий “Твит”
beginPresentation :: Presentation -> State Conference ()
beginPresentation title = currentPresentation .= title
34
Сценарий “Начать доклад”
setListeners :: [Person] -> State Conference ()
setListeners persons = setVisited (attendees . onlyListeners persons)
onlyListeners :: Persons -> Traversal' [Attendee] Attendee
onlyListeners persons
= traversed . filtered (att -> (att ^. person) `elem` persons)
35
Сценарий “Задать слушателей”
conferenceScenario :: State Conference ()
conferenceScenario = do
alex `tweeted` "Rush hour, sorry. #conf"
beginPresentation "Multilanguage projects"
setListeners [pete, jakob, lana]
jakob `tweeted` "Great talk! #conf"
lana `tweeted` "So technical. #conf"
pete `tweeted` "#MLP 222 coming soon."
36
Сценарий “Конференция”
Линзы в других языках
● Haskell
○ Edward Kmett, “Lenses, Folds, and Traversals”
● Scalaz
○ Edward Kmett, “Lenses: A Functional Imperative”
● JavaScript
● Clojure
● C++ (!)
● … your language
37
38
Спасибо за внимание!
Вопросы?
Александр Гранин
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)
39

More Related Content

PDF
Линзы - комбинаторная манипуляция данными Александр Гранин Dev2Dev v2.0 30.05...
PPTX
Topological indices (t is) of the graphs to seek qsar models of proteins com...
ODP
My app is secure... I think
PDF
Benchmarking Perl (Chicago UniForum 2006)
ODP
The promise of asynchronous php
PDF
R57shell
ODP
My app is secure... I think
PDF
Method::Signatures
Линзы - комбинаторная манипуляция данными Александр Гранин Dev2Dev v2.0 30.05...
Topological indices (t is) of the graphs to seek qsar models of proteins com...
My app is secure... I think
Benchmarking Perl (Chicago UniForum 2006)
The promise of asynchronous php
R57shell
My app is secure... I think
Method::Signatures

What's hot (20)

PDF
The Perl6 Type System
PDF
Creating a compiler in Perl 6
ODP
Caching and tuning fun for high scalability @ LOAD2012
ODP
My app is secure... I think
ODP
Beyond php - it's not (just) about the code
ODP
My app is secure... I think
PDF
Models and Service Layers, Hemoglobin and Hobgoblins
TXT
PPTX
Dropping ACID with MongoDB
PDF
Adventures in Optimization
PPTX
TXT
Wsomdp
ODP
My app is secure... I think
PDF
Command Bus To Awesome Town
PDF
Introdução ao Perl 6
TXT
Gta v savegame
PDF
Twitter codeigniter library
PDF
Things I Believe Now That I'm Old
PDF
You Got Async in my PHP!
PDF
Wx::Perl::Smart
The Perl6 Type System
Creating a compiler in Perl 6
Caching and tuning fun for high scalability @ LOAD2012
My app is secure... I think
Beyond php - it's not (just) about the code
My app is secure... I think
Models and Service Layers, Hemoglobin and Hobgoblins
Dropping ACID with MongoDB
Adventures in Optimization
Wsomdp
My app is secure... I think
Command Bus To Awesome Town
Introdução ao Perl 6
Gta v savegame
Twitter codeigniter library
Things I Believe Now That I'm Old
You Got Async in my PHP!
Wx::Perl::Smart
Ad

Similar to Линзы - комбинаторная манипуляция данными (Dev2Dev) (20)

KEY
Why ruby
PDF
Type safe embedded domain-specific languages
PDF
Damn Fine CoffeeScript
PDF
Elm: give it a try
PDF
WTF Oriented Programming, com Fabio Akita
PDF
Линзы - комбинаторная манипуляция данными
PDF
PostgreSQL Open SV 2018
KEY
Intro to Ruby - Twin Cities Code Camp 7
PDF
Дмитрий Верескун «Синтаксический сахар C#»
KEY
Ruby/Rails
PPTX
Powershell for Log Analysis and Data Crunching
PDF
Beware: Sharp Tools
PDF
Ruby and Rails by example
PDF
Rails-like JavaScript Using CoffeeScript, Backbone.js and Jasmine
ODP
Parsing with Perl6 Grammars
KEY
Let's build a parser!
KEY
Tres Gemas De Ruby
PDF
Refactoring to Macros with Clojure
PDF
Ruby and Rails by Example (GeekCamp edition)
PDF
Ams adapters
Why ruby
Type safe embedded domain-specific languages
Damn Fine CoffeeScript
Elm: give it a try
WTF Oriented Programming, com Fabio Akita
Линзы - комбинаторная манипуляция данными
PostgreSQL Open SV 2018
Intro to Ruby - Twin Cities Code Camp 7
Дмитрий Верескун «Синтаксический сахар C#»
Ruby/Rails
Powershell for Log Analysis and Data Crunching
Beware: Sharp Tools
Ruby and Rails by example
Rails-like JavaScript Using CoffeeScript, Backbone.js and Jasmine
Parsing with Perl6 Grammars
Let's build a parser!
Tres Gemas De Ruby
Refactoring to Macros with Clojure
Ruby and Rails by Example (GeekCamp edition)
Ams adapters
Ad

More from Alexander Granin (20)

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

Recently uploaded (20)

PDF
Network Security Unit 5.pdf for BCA BBA.
PDF
Building Integrated photovoltaic BIPV_UPV.pdf
PDF
Empathic Computing: Creating Shared Understanding
PPTX
1. Introduction to Computer Programming.pptx
PDF
Encapsulation_ Review paper, used for researhc scholars
PPTX
Tartificialntelligence_presentation.pptx
PDF
Assigned Numbers - 2025 - Bluetooth® Document
PDF
MIND Revenue Release Quarter 2 2025 Press Release
PDF
Optimiser vos workloads AI/ML sur Amazon EC2 et AWS Graviton
PDF
Electronic commerce courselecture one. Pdf
PDF
Unlocking AI with Model Context Protocol (MCP)
PDF
Diabetes mellitus diagnosis method based random forest with bat algorithm
PPTX
Digital-Transformation-Roadmap-for-Companies.pptx
PDF
Dropbox Q2 2025 Financial Results & Investor Presentation
PDF
Advanced methodologies resolving dimensionality complications for autism neur...
PDF
Approach and Philosophy of On baking technology
PDF
Getting Started with Data Integration: FME Form 101
PPTX
Spectroscopy.pptx food analysis technology
PDF
Video forgery: An extensive analysis of inter-and intra-frame manipulation al...
PPTX
20250228 LYD VKU AI Blended-Learning.pptx
Network Security Unit 5.pdf for BCA BBA.
Building Integrated photovoltaic BIPV_UPV.pdf
Empathic Computing: Creating Shared Understanding
1. Introduction to Computer Programming.pptx
Encapsulation_ Review paper, used for researhc scholars
Tartificialntelligence_presentation.pptx
Assigned Numbers - 2025 - Bluetooth® Document
MIND Revenue Release Quarter 2 2025 Press Release
Optimiser vos workloads AI/ML sur Amazon EC2 et AWS Graviton
Electronic commerce courselecture one. Pdf
Unlocking AI with Model Context Protocol (MCP)
Diabetes mellitus diagnosis method based random forest with bat algorithm
Digital-Transformation-Roadmap-for-Companies.pptx
Dropbox Q2 2025 Financial Results & Investor Presentation
Advanced methodologies resolving dimensionality complications for autism neur...
Approach and Philosophy of On baking technology
Getting Started with Data Integration: FME Form 101
Spectroscopy.pptx food analysis technology
Video forgery: An extensive analysis of inter-and intra-frame manipulation al...
20250228 LYD VKU AI Blended-Learning.pptx

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

  • 2. О себе ● Haskell, C++, немного C# ● Организатор сообщества LambdaNsk ● Доклады: o Haskell. DevDay@2GIS o ФП вчера и сегодня. TechTalks@NSU o Функционально-декларативный дизайн на С++ o Идиоматичный ФП-код. LambdaNsk 2
  • 3. ● Очень кратко о ФП ● Линзы в Haskell ● Сценарии с использованием линз ● Линзы в других языках План доклада 3
  • 4. Функциональное программирование ● Функции высших порядков ● Лямбды ● Замыкания ● Иммутабельность ● Рекурсия 4
  • 5. Функциональное программирование ● Функции высших порядков ● Лямбды ● Замыкания ● Иммутабельность ● Рекурсия ● Математические абстракции 5
  • 6. data Credentials = Credentials { credentialsLogin :: String, credentialsPassword :: String } Credentials Login Password 6 Простой алгебраический тип данных
  • 7. updatePassword credentials newPassword = let (Credentials login _) = credentials in (Credentials login newPassword) updatePassword2 credentials newPassword = credentials { credentialsPassword = newPassword } Изменение значения простого АТД 7 data Credentials = Credentials { credentialsLogin :: String, credentialsPassword :: String } Credentials Login Password
  • 8. data Credentials = Credentials { credentialsLogin :: String, credentialsPassword :: String } data Person = Person { personName :: String, personSurname :: String, personCredentials :: Credentials } 8 Более сложный АТД Person Credentials Login Password Credentials Login Password Credentials Name Surname
  • 9. updatePersonPassword person newPass = let credentials = personCredentials person newCreds = credentials { credentialsPassword = newPass } newPerson = person { personCredentials = newCreds } in newPerson 9 Изменение более сложного АТД
  • 10. data Credentials = Credentials { credentialsLogin :: String, credentialsPassword :: String } data Person = Person { personName :: String, personSurname :: String, personCredentials :: Credentials } data Subscriber = Subscriber { subscriberPerson :: Person, subscriberTariffId :: Int } Person Subscriber Credentials Login Password 10 А что, если?..
  • 11. updateSubscriberPassword subscriber newPass = let person = subscriberPerson subscriber credentials = personCredentials person newCreds = credentials { credentialsPassword = newPass } newPerson = person { personCredentials = newCreds } newSubscriber = subscriber { subscriberPerson = newPerson } in newSubscriber 11
  • 12. updateSubscriberPassword subscriber newPass = let person = subscriberPerson subscriber credentials = personCredentials person newCreds = credentials { credentialsPassword = newPass } newPerson = person { personCredentials = newCreds } newSubscriber = subscriber { subscriberPerson = newPerson } in newSubscriber Getters Setters 12
  • 13. person = subscriberPerson subscriber newSubscriber = subscriber { subscriberPerson = person } credentials = personCredentials person newPerson = person { personCredentials = credentials } password = credentialsPassword credentials newCreds = credentials { credentialsPassword = password } b = getB a a = setB b a 13
  • 14. getPerson subscriber = subscriberPerson subscriber setPerson subscriber person = subscriber { subscriberPerson = person } getCredentials person = personCredentials person setCredentials person creds = person { personCredentials = creds } getPassword creds = credentialsPassword creds setPassword creds pass = creds { credentialsPassword = pass } b = getB a a = setB b a 14 getter :: A -> B setter :: A -> B -> A
  • 15. Линза = Геттер + Сеттер lens :: (getter :: A -> B, setter :: A -> B -> A) passwordLens :: (Credentials -> String, Credentials -> String -> Credentials) passwordLens = (getPass, setPass) where getPass creds = credentialsPassword creds setPass creds newPass = creds {credentialsPassword = newPass} 15
  • 16. Простые операторы view и set view (getter, _) parent = getter parent set (_, setter) parent value = setter parent value > let myCredentials = Credentials "login" "pass" > view passwordLens myCredentials "pass" > set passwordLens myCredentials "qwerty" Credentials "login" "qwerty" 16
  • 17. credentialsLens = (getCreds, setCreds) where getCreds person = personCredentials person setCreds person newCreds = person {personCredentials = newCreds} personLens = (getPerson, setPerson) where getPerson subscr = subscriberPerson subscr setPerson subscr newPers = subscr {subscriberPerson = newPers} Еще линзы 17
  • 18. (getChild, setChild) . (getValue, setValue) = (getter, setter) where getter parent = getValue (getChild parent) setter parent value = let oldChild = getChild parent newChild = setValue oldChild value in setChild parent newChild Линза . линза = линза 18 Композиция!
  • 19. myCredentials = Credentials "login" "pass" mePerson = Person "Alex" "Granin" myCredentials > view (credentialsLens . passwordLens) mePerson “pass” > set (credentialsLens . passwordLens) mePerson “qwerty” Person "Alex" "Granin" (Credentials "login" "qwerty") Линза . линза = линза 19
  • 20. Линзы в Haskell: библиотека lens Автор - Edward Kmett 20
  • 21. data ContactType = VK | FB | Twitter | Email data Skill = Cpp | CSharp | Haskell | Java | FSharp | Python data Person = Person { _name :: String, _surname :: String, _contacts :: [(ContactType, String)], _skills :: [Skill] } АТД Person Person Name Surname Contacts Skills 21
  • 22. type Presentation = String data Attendee = Speaker { _person :: Person, _visited :: [Presentation], _presentationTitle :: String } | Attendee { _person :: Person, _visited :: [Presentation] } АТД Attendee Attendee Person Name Surname Contacts Skills 22
  • 23. -- Template Haskell rocks: makeLenses ''Person makeLenses ''Attendee Создание линз _name name Person ===> String _surname surname Person ===> String _contacts contacts Person ===> Contacts _person person Attendee ===> Person _visited visited Attendee ===> 23
  • 24. pete = Person "Pete" "Howard" [(FB, "pete")] [Java, Python] peteAttendee = Attendee pete [] > _name (_person peteAttendee) -- Manual “Pete” > view (person.name) peteAttendee -- With lenses “Pete” > peteAttendee ^. (person.name) -- The same “Pete” Оператор view (^.) 24
  • 25. > peteAttendee ^. person.skills [Java,Python] > itoList (peteAttendee ^. person.skills) [(0,Java),(1,Python)] > (itoList (peteAttendee ^. person.skills)) ^.. ix 1 [(1,Python)] Операторы itoList, (^..) и ix 25
  • 26. setAttendeeName att n = case att of Speaker pers visit theme -> Speaker (setName pers) visit theme Attendee pers visit -> Attendee (setName pers) visit where setName (Person _ s cts skls) = Person n s cts skls setAttendeeName’ att n = set (person.name) "Jack" att Оператор set 26
  • 27. addContact att contact = case att of Speaker pers visit theme -> Speaker (appendContact pers) visit theme Attendee pers visit -> Attendee (appendContact pers) visit where appendContact (Person n s cts skls) = Person n s (contact : cts) skls addContact' att contact = over (person . contacts) (insert contact) att Оператор over 27
  • 28. #%%= **= //= //~ <<%@= <<.|.= <<^~ %= ... #%%~ **~ <-= <#%= <<%@~ <<.|.~ <<||= %@= .= #%= *= <-~ <#%~ <<%~ <<.~ <<||~ %@~ .> #%~ *~ <. <#= <<&&= <<//= <<~ %~ .@= #= += <.&.= <#~ <<&&~ <<//~ <>= & .@~ #~ +~ <.&.~ <%= <<**= <</>= <>~ &&= .|.= %%= -= <.= <%@= <<**~ <</>~ <?= &&~ .|.~ %%@= -~ <.> <%@~ <<*= <<<.>= <?~ &~ .~ %%@~ .&.= <.>= <%~ <<*~ <<<.>~ <^= <.|.= <<-= %%~ .&.~ <.>~ <&&= <<+= <<</>= <^^= <.|.~ <<-~ Тысячи их... Zen 28
  • 30. data Conference = Conference { _attendees :: [Attendee], _currentPresentation :: Presentation, _conferenceTweets :: [(Presentation, Person, String)] } АТД Conference Attendee Person Conference currentPresentation conferenceTweets 30
  • 31. pete = Person "Pete" "Howard" [facebook "pete"] [Java] jakob = Person "Jakob" "Brown" [twitter "jab"] [Java, CSharp] lana = Person "Lana" "Dell" [] [FSharp] alex = Person "Alexander" "Granin" [vk "graninas"] [Haskell] guru = Person "Real" "Guru" [] [Cpp, Java, CSharp, Haskell] confAttendees = [ attendee pete, attendee jakob, attendee lana, speaker alex "Lenses", speaker guru “Multilanguage projects”] conference = Conference confAttendees "" [] 31
  • 32. conferenceScenario :: State Conference () conferenceScenario = do alex `tweeted` "Rush hour, sorry. #dev2dev" beginPresentation "Multilanguage projects" setListeners [pete, jakob, lana] jakob `tweeted` "Great talk! #dev2dev" lana `tweeted` "So technical. #dev2dev" pete `tweeted` "#MLP 222 coming soon." 32 Сценарий “Конференция”
  • 33. tweeted :: Person -> Msg -> State Conference () tweeted pers msg = if "#dev2dev" `isInfixOf` msg then writeTweet pers msg else return () writeTweet :: Person -> Msg -> State Conference () writeTweet pers msg = do presentationName <- use currentPresentation conferenceTweets %= insert (presentationName, pers, msg) 33 Сценарий “Твит”
  • 34. beginPresentation :: Presentation -> State Conference () beginPresentation title = currentPresentation .= title 34 Сценарий “Начать доклад”
  • 35. setListeners :: [Person] -> State Conference () setListeners persons = setVisited (attendees . onlyListeners persons) onlyListeners :: Persons -> Traversal' [Attendee] Attendee onlyListeners persons = traversed . filtered (att -> (att ^. person) `elem` persons) 35 Сценарий “Задать слушателей”
  • 36. conferenceScenario :: State Conference () conferenceScenario = do alex `tweeted` "Rush hour, sorry. #conf" beginPresentation "Multilanguage projects" setListeners [pete, jakob, lana] jakob `tweeted` "Great talk! #conf" lana `tweeted` "So technical. #conf" pete `tweeted` "#MLP 222 coming soon." 36 Сценарий “Конференция”
  • 37. Линзы в других языках ● Haskell ○ Edward Kmett, “Lenses, Folds, and Traversals” ● Scalaz ○ Edward Kmett, “Lenses: A Functional Imperative” ● JavaScript ● Clojure ● C++ (!) ● … your language 37
  • 39. 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) 39