SlideShare una empresa de Scribd logo
1 de 23
Descargar para leer sin conexión
Essence
ofthe
iteratorpatternMarkus Klink, @joheinz, markus.klink@inoio.de
Goal
“Imperative iterations using the pattern have two
simultaneous aspects: mapping and accumulating.”
Jeremy Gibbons & Bruno C. d. S. Oliveira
Markus Klink, @joheinz, markus.klink@inoio.de
Functionalmappingand
accumulating
trait Traverse[F[_]] extends Functor[F] with Foldable[F] {
def traverse[G[_]: Applicative, A, B](fa: F[A])(f: A => G[B]): G[F[B]]
}
trait Applicative[F[_]] extends Functor[F] {
def ap[A,B](fa: F[A])(f: F[A => B]) : F[B]
def pure(a: A) : F[A]
def map[A,B](fa: F[A])(f: A => B) : F[B] = ap(fa)(pure(f))
}
Traverse takes a structure F[A], injects each element
via the function f: A => G[B] into an Applicative
G[_] and combines the results into G[F[B] using the
applicative instance of G.
Markus Klink, @joheinz, markus.klink@inoio.de
Acloser look
trait Foldable[F[_]] {
def foldRight[A, B](fa: F[A], z: => B)(f: (A, B) => B): B
}
trait Traverse[F[_]] extends Functor[F] with Foldable[F] {
def traverse[G[_]: Applicative, A, B](fa: F[A])(f: A => G[B]): G[F[B]]
}
Look at the similarities!
Markus Klink, @joheinz, markus.klink@inoio.de
Traversing is "almost" like
Folding:
» Look! No zero element:
def foldRight[A, B](fa: F[A], z: => B)(f: (A, B) => B): B
def traverse[G[_]: Applicative, A, B](fa: F[A])(f: A => G[B]): G[F[B]]
» Look! B is wrapped in an Applicative and our F:
def foldRight[A, B](fa: F[A], z: => B)(f: (A, B) => B): B
def traverse[G[_]: Applicative, A, B](fa: F[A])(f: A => G[B]): G[F[B]]
Markus Klink, @joheinz, markus.klink@inoio.de
Accumulating
Markus Klink, @joheinz, markus.klink@inoio.de
val l = List(1,2,3)
val result: Future[List[String]] = l.traverse(a => Future.successful { a.toString })
How?
// traverse implementation of List, G[_] is the future
override def traverse[G[_]: Applicative, A, B](fa: List[A])(f: (A) => G[B]): G[List[B]] = {
val emptyListInG: G[List[B]] = Applicative[G].pure(List.empty[B]) // if the list is empty we need a Future { List.empty() }
// f(a) gives us another G[B], which we can inject into B => B => Future[List[B]]
foldRight(fa, emptyListInG) { (a: A, fbs: G[List[B]]) => Applicative[G].apply2(f(a), fbs)(_ +: _) }
}
// applicative instance of Future, example...
override def ap[A,B](F: => Future[A])(f: => Future[A => B]) : Future[B] = {
for {
a <- F
g <- f
} yield { g(a) }
}
Markus Klink, @joheinz, markus.klink@inoio.de
Gibbons & Oliveiraclaimthatwe
can do:
val x : List[Char]= "1234".toList
val result : Int = x.traverse(c => ???)
assert(4 == result)
The claim is that we can accumulate values, or write
the length function just with Traverse/Applicative
Markus Klink, @joheinz, markus.klink@inoio.de
How?
» we need a result type G[List[Int]] which equals
Int
» G needs to be an applicative
» we need to calculate a sum of all the values.
» we need a zero value in case the list is empty,
because of ...
val emptyListInG: G[List[B]] =
Applicative[G].pure(List.empty[B])
Markus Klink, @joheinz, markus.klink@inoio.de
Each Monoid gives risetoan
applicative
trait Monoid[F] extends Semigroup[F] {
self =>
/**
* the identity element.
*/
def zero: F
def applicative: Applicative[Lambda[a => F]] = new Applicative[Lambda[a => F]] {
// mapping just returns ourselves
override def map[A, B](fa: F)(f: A => B) : F = fa
// putting any value into this Applicative will put the Monoid.zero in it
def pure[A](a: => A): F = self.zero
// Applying this Applicative combines each value with the append function.
def ap[A, B](fa: => F)(f: => F): F = self.append(f, fa)
}
Markus Klink, @joheinz, markus.klink@inoio.de
How2
Part of the trick is this type: Applicative[Lambda[a
=> F]]!
It means that we throw everything away and create a
type G[_] which behaves like F. So...
val x : List[Char]= "1234".toList
val charCounter : Applicative[Lambda[a => Int]] = Monoid[Int].applicative
// we just "reversed" the parameters of traverse
// the summing is done automatically via append
charCounter.traverse(x)(_ => 1)
Markus Klink, @joheinz, markus.klink@inoio.de
Counting lines
In the previous example we assigned each char in the
list to a 1 and let the Monoid do the work.
val x : List[Char] = "1233n1234n"
val lineCounter : Applicative[Lambda[a => Int]] = Monoid[Int].applicative
lineCounter.traverse(x){c => if (c == 'n') 1 else 0 }
Markus Klink, @joheinz, markus.klink@inoio.de
Products ofApplicatives
Doing bothatthe sametimewithinasingle
traversal
val x : List[Char]= "1234n1234n"
val counter : Applicative[Lambda[a => Int]] = Monoid[Int].applicative
val charLineApp : Applicative[Lambda[a => (Int, Int)]] =
counter.product[Lambda[a => Int](counter)
val (chars, lines) = counter.traverse(x){c => (1 -> if (c == 'n') 1 else 0 }
Markus Klink, @joheinz, markus.klink@inoio.de
Countingwords
Counting words cannot work on the current position
alone. We need to track changes from spaces to non
spaces to recognize the beginning of a new word.
def atWordStart(c: Char): State[Boolean, Int] = State { (prev: Boolean) =>
val cur = c != ' '
(cur, if (!prev && cur) 1 else 0)
}
val WordCount : Applicative[Lambda[a => Int]] =
State.stateMonad[Boolean].compose[Lambda[a => Int](counter)
val StateWordCount = WordCount.traverse(text)(c => atWordStart(c))
StateWordCount.eval(false)
Markus Klink, @joheinz, markus.klink@inoio.de
Usingthe productofall3
countersto implementwc
val AppCharLinesWord: Applicative[Lambda[a => ((Int, Int), State[Boolean, Int])]] =
Count // char count
.product[Lambda[a => Int]](Count) // line count
.product[Lambda[a => State[Boolean, Int]]](WordCount) // word count
val ((charCount, lineCount), wordCountState) = AppCharLinesWord.traverse(text)((c: Char) =>
((1, if (c == 'n') 1 else 0), atWordStart(c)))
val wordCount: Int = wordCountState.eval(false)
Markus Klink, @joheinz, markus.klink@inoio.de
Collecting some
state
and modifying
elements
Markus Klink, @joheinz, markus.klink@inoio.de
// start value
public Integer count = 0;
public Collection<Person> collection = ...;
for (e <- collection) {
// or we use an if
count = count + 1;
// side effecting function
// or we map into another collection
e.modify();
}
Obviously in a functional programming language, we
would not want to modify the collection but get back
a new collection.
We also would like to get the (stateful) counter
back.
Markus Klink, @joheinz, markus.klink@inoio.de
def collect[G[_]: Applicative, A, B](fa: F[A])(f: A => G[Unit])(g: A => B): G[F[B]] =
{
val G = implicitly[Applicative[G]]
val applicationFn : A => G[B] = a => G.ap(f(a))(G.pure((u: Unit) => g(a)))
self.traverse(fa)(applicationFn)
}
def collectS[S, A, B](fa: F[A])(f: A => State[S, Unit])(g: A => B): State[S, F[B]] =
{
collect[Lambda[a => State[S, a]], A, B](fa)(f)(g)
}
val list : List[Person] = ...
val stateMonad = State.stateMonad[Int]
val (counter, updatedList) = list.collectS{
a => for { count <- get; _ <- put(count + 1) } yield ()}(p => p.modify()).run(0)
Markus Klink, @joheinz, markus.klink@inoio.de
Modifying elements
depending on some
state
Markus Klink, @joheinz, markus.klink@inoio.de
// start value
public Collection<Person> collection = ...;
for (e <- collection) {
e.modify(stateful());
}
Now the modification depends on some state we are
collecting.
Markus Klink, @joheinz, markus.klink@inoio.de
def disperse[G[_]: Applicative, A, B, C](fa: F[A])(fb: G[B], g: A => B => C): G[F[C]] =
{
val G = implicitly[Applicative[G]]
val applicationFn: A => G[C] = a => G.ap(fb)(G.pure(g(a)))
self.traverse(fa)(applicationFn)
}
def disperseS[S, A, C](fa: F[A])(fb: State[S, S], g: A => S => C) : State[S,F[C]] =
{
disperse[Lambda[a => State[S, a]], A, S, C](fa)(fb, g)
}
Markus Klink, @joheinz, markus.klink@inoio.de
THANKS
Markus Klink, @joheinz, markus.klink@inoio.de
Some resources
http://etorreborre.blogspot.de/2011/06/essence-of-
iterator-pattern.html
Markus Klink, @joheinz, markus.klink@inoio.de

Más contenido relacionado

La actualidad más candente

SAMSTAR: A Semi-automated Lexical Method to generate Star Schemas from an ERD
SAMSTAR: A Semi-automated Lexical Method to generate Star Schemas from an ERDSAMSTAR: A Semi-automated Lexical Method to generate Star Schemas from an ERD
SAMSTAR: A Semi-automated Lexical Method to generate Star Schemas from an ERD
The Children's Hospital of Philadelphia
 
SupportVectorRegression
SupportVectorRegressionSupportVectorRegression
SupportVectorRegression
Daniel K
 
BIometrics- plotting DET and EER curve using Matlab
BIometrics- plotting DET and EER curve using MatlabBIometrics- plotting DET and EER curve using Matlab
BIometrics- plotting DET and EER curve using Matlab
Shiv Koppad
 

La actualidad más candente (20)

Fp in scala with adts part 2
Fp in scala with adts part 2Fp in scala with adts part 2
Fp in scala with adts part 2
 
10 - Scala. Co-product type (sum type)
10 - Scala. Co-product type (sum type)10 - Scala. Co-product type (sum type)
10 - Scala. Co-product type (sum type)
 
CLASS XII COMPUTER SCIENCE MONTHLY TEST PAPER
CLASS XII COMPUTER SCIENCE MONTHLY TEST  PAPERCLASS XII COMPUTER SCIENCE MONTHLY TEST  PAPER
CLASS XII COMPUTER SCIENCE MONTHLY TEST PAPER
 
C programs Set 2
C programs Set 2C programs Set 2
C programs Set 2
 
Qno 3 (a)
Qno 3 (a)Qno 3 (a)
Qno 3 (a)
 
statistical computation using R- an intro..
statistical computation using R- an intro..statistical computation using R- an intro..
statistical computation using R- an intro..
 
Qno 2 (c)
Qno 2 (c)Qno 2 (c)
Qno 2 (c)
 
Cs practical file
Cs practical fileCs practical file
Cs practical file
 
Fp in scala part 1
Fp in scala part 1Fp in scala part 1
Fp in scala part 1
 
SAMSTAR: A Semi-automated Lexical Method to generate Star Schemas from an ERD
SAMSTAR: A Semi-automated Lexical Method to generate Star Schemas from an ERDSAMSTAR: A Semi-automated Lexical Method to generate Star Schemas from an ERD
SAMSTAR: A Semi-automated Lexical Method to generate Star Schemas from an ERD
 
Modules and Scripts- Python Assignment Help
Modules and Scripts- Python Assignment HelpModules and Scripts- Python Assignment Help
Modules and Scripts- Python Assignment Help
 
SupportVectorRegression
SupportVectorRegressionSupportVectorRegression
SupportVectorRegression
 
N-Queens Combinatorial Problem - Polyglot FP for fun and profit - Haskell and...
N-Queens Combinatorial Problem - Polyglot FP for fun and profit - Haskell and...N-Queens Combinatorial Problem - Polyglot FP for fun and profit - Haskell and...
N-Queens Combinatorial Problem - Polyglot FP for fun and profit - Haskell and...
 
Matlab integration
Matlab integrationMatlab integration
Matlab integration
 
BIometrics- plotting DET and EER curve using Matlab
BIometrics- plotting DET and EER curve using MatlabBIometrics- plotting DET and EER curve using Matlab
BIometrics- plotting DET and EER curve using Matlab
 
Monoids - Part 1 - with examples using Scalaz and Cats
Monoids - Part 1 - with examples using Scalaz and CatsMonoids - Part 1 - with examples using Scalaz and Cats
Monoids - Part 1 - with examples using Scalaz and Cats
 
An Introduction to Functional Programming using Haskell
An Introduction to Functional Programming using HaskellAn Introduction to Functional Programming using Haskell
An Introduction to Functional Programming using Haskell
 
Rumus visual basic
Rumus visual basicRumus visual basic
Rumus visual basic
 
OPERATOR IN PYTHON-PART1
OPERATOR IN PYTHON-PART1OPERATOR IN PYTHON-PART1
OPERATOR IN PYTHON-PART1
 
Rethinking metrics: metrics 2.0 @ Lisa 2014
Rethinking metrics: metrics 2.0 @ Lisa 2014Rethinking metrics: metrics 2.0 @ Lisa 2014
Rethinking metrics: metrics 2.0 @ Lisa 2014
 

Destacado (8)

Matuura cpp
Matuura cppMatuura cpp
Matuura cpp
 
Objc lambda
Objc lambdaObjc lambda
Objc lambda
 
SPL fukuokaphp_1
SPL fukuokaphp_1SPL fukuokaphp_1
SPL fukuokaphp_1
 
連邦の白いヤツ 「Objective-C」
連邦の白いヤツ 「Objective-C」連邦の白いヤツ 「Objective-C」
連邦の白いヤツ 「Objective-C」
 
Chakkason.pptx
Chakkason.pptxChakkason.pptx
Chakkason.pptx
 
型! 型!
型! 型!型! 型!
型! 型!
 
The Essence of the Iterator Pattern
The Essence of the Iterator PatternThe Essence of the Iterator Pattern
The Essence of the Iterator Pattern
 
Iterator Pattern
Iterator PatternIterator Pattern
Iterator Pattern
 

Similar a Essence of the iterator pattern

Monads do not Compose
Monads do not ComposeMonads do not Compose
Monads do not Compose
Philip Schwarz
 
Algebraic Data Types and Origami Patterns
Algebraic Data Types and Origami PatternsAlgebraic Data Types and Origami Patterns
Algebraic Data Types and Origami Patterns
Vasil Remeniuk
 
Modular Module Systems
Modular Module SystemsModular Module Systems
Modular Module Systems
league
 
Monad presentation scala as a category
Monad presentation   scala as a categoryMonad presentation   scala as a category
Monad presentation scala as a category
samthemonad
 

Similar a Essence of the iterator pattern (20)

Monads do not Compose
Monads do not ComposeMonads do not Compose
Monads do not Compose
 
(2015 06-16) Three Approaches to Monads
(2015 06-16) Three Approaches to Monads(2015 06-16) Three Approaches to Monads
(2015 06-16) Three Approaches to Monads
 
Algebraic Data Types and Origami Patterns
Algebraic Data Types and Origami PatternsAlgebraic Data Types and Origami Patterns
Algebraic Data Types and Origami Patterns
 
Modular Module Systems
Modular Module SystemsModular Module Systems
Modular Module Systems
 
Building Functions
Building FunctionsBuilding Functions
Building Functions
 
Embedding Generic Monadic Transformer into Scala. [Tfp2022]
Embedding Generic Monadic Transformer into Scala. [Tfp2022]Embedding Generic Monadic Transformer into Scala. [Tfp2022]
Embedding Generic Monadic Transformer into Scala. [Tfp2022]
 
Functions, Types, Programs and Effects
Functions, Types, Programs and EffectsFunctions, Types, Programs and Effects
Functions, Types, Programs and Effects
 
Scala Functional Patterns
Scala Functional PatternsScala Functional Patterns
Scala Functional Patterns
 
Monad and Algebraic Design in Functional Programming
Monad and Algebraic Design in Functional ProgrammingMonad and Algebraic Design in Functional Programming
Monad and Algebraic Design in Functional Programming
 
Quark: A Purely-Functional Scala DSL for Data Processing & Analytics
Quark: A Purely-Functional Scala DSL for Data Processing & AnalyticsQuark: A Purely-Functional Scala DSL for Data Processing & Analytics
Quark: A Purely-Functional Scala DSL for Data Processing & Analytics
 
Monads and friends demystified
Monads and friends demystifiedMonads and friends demystified
Monads and friends demystified
 
Monad Transformers - Part 1
Monad Transformers - Part 1Monad Transformers - Part 1
Monad Transformers - Part 1
 
Monad presentation scala as a category
Monad presentation   scala as a categoryMonad presentation   scala as a category
Monad presentation scala as a category
 
Blazing Fast, Pure Effects without Monads — LambdaConf 2018
Blazing Fast, Pure Effects without Monads — LambdaConf 2018Blazing Fast, Pure Effects without Monads — LambdaConf 2018
Blazing Fast, Pure Effects without Monads — LambdaConf 2018
 
The Essence of the Iterator Pattern (pdf)
The Essence of the Iterator Pattern (pdf)The Essence of the Iterator Pattern (pdf)
The Essence of the Iterator Pattern (pdf)
 
Monad Fact #4
Monad Fact #4Monad Fact #4
Monad Fact #4
 
Composition birds-and-recursion
Composition birds-and-recursionComposition birds-and-recursion
Composition birds-and-recursion
 
Fp in scala part 2
Fp in scala part 2Fp in scala part 2
Fp in scala part 2
 
Generic Functional Programming with Type Classes
Generic Functional Programming with Type ClassesGeneric Functional Programming with Type Classes
Generic Functional Programming with Type Classes
 
Algebraic Thinking for Evolution of Pure Functional Domain Models
Algebraic Thinking for Evolution of Pure Functional Domain ModelsAlgebraic Thinking for Evolution of Pure Functional Domain Models
Algebraic Thinking for Evolution of Pure Functional Domain Models
 

Último

%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...
%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...
%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...
masabamasaba
 
Abortion Pill Prices Tembisa [(+27832195400*)] 🏥 Women's Abortion Clinic in T...
Abortion Pill Prices Tembisa [(+27832195400*)] 🏥 Women's Abortion Clinic in T...Abortion Pill Prices Tembisa [(+27832195400*)] 🏥 Women's Abortion Clinic in T...
Abortion Pill Prices Tembisa [(+27832195400*)] 🏥 Women's Abortion Clinic in T...
Medical / Health Care (+971588192166) Mifepristone and Misoprostol tablets 200mg
 
%+27788225528 love spells in Toronto Psychic Readings, Attraction spells,Brin...
%+27788225528 love spells in Toronto Psychic Readings, Attraction spells,Brin...%+27788225528 love spells in Toronto Psychic Readings, Attraction spells,Brin...
%+27788225528 love spells in Toronto Psychic Readings, Attraction spells,Brin...
masabamasaba
 
%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...
%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...
%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...
masabamasaba
 

Último (20)

Direct Style Effect Systems - The Print[A] Example - A Comprehension Aid
Direct Style Effect Systems -The Print[A] Example- A Comprehension AidDirect Style Effect Systems -The Print[A] Example- A Comprehension Aid
Direct Style Effect Systems - The Print[A] Example - A Comprehension Aid
 
%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
 
%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...
%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...
%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...
 
WSO2CON 2024 - WSO2's Digital Transformation Journey with Choreo: A Platforml...
WSO2CON 2024 - WSO2's Digital Transformation Journey with Choreo: A Platforml...WSO2CON 2024 - WSO2's Digital Transformation Journey with Choreo: A Platforml...
WSO2CON 2024 - WSO2's Digital Transformation Journey with Choreo: A Platforml...
 
WSO2Con2024 - WSO2's IAM Vision: Identity-Led Digital Transformation
WSO2Con2024 - WSO2's IAM Vision: Identity-Led Digital TransformationWSO2Con2024 - WSO2's IAM Vision: Identity-Led Digital Transformation
WSO2Con2024 - WSO2's IAM Vision: Identity-Led Digital Transformation
 
MarTech Trend 2024 Book : Marketing Technology Trends (2024 Edition) How Data...
MarTech Trend 2024 Book : Marketing Technology Trends (2024 Edition) How Data...MarTech Trend 2024 Book : Marketing Technology Trends (2024 Edition) How Data...
MarTech Trend 2024 Book : Marketing Technology Trends (2024 Edition) How Data...
 
What Goes Wrong with Language Definitions and How to Improve the Situation
What Goes Wrong with Language Definitions and How to Improve the SituationWhat Goes Wrong with Language Definitions and How to Improve the Situation
What Goes Wrong with Language Definitions and How to Improve the Situation
 
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
 
%in ivory park+277-882-255-28 abortion pills for sale in ivory park
%in ivory park+277-882-255-28 abortion pills for sale in ivory park %in ivory park+277-882-255-28 abortion pills for sale in ivory park
%in ivory park+277-882-255-28 abortion pills for sale in ivory park
 
tonesoftg
tonesoftgtonesoftg
tonesoftg
 
%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
 
%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
 
Abortion Pill Prices Tembisa [(+27832195400*)] 🏥 Women's Abortion Clinic in T...
Abortion Pill Prices Tembisa [(+27832195400*)] 🏥 Women's Abortion Clinic in T...Abortion Pill Prices Tembisa [(+27832195400*)] 🏥 Women's Abortion Clinic in T...
Abortion Pill Prices Tembisa [(+27832195400*)] 🏥 Women's Abortion Clinic in T...
 
%+27788225528 love spells in Toronto Psychic Readings, Attraction spells,Brin...
%+27788225528 love spells in Toronto Psychic Readings, Attraction spells,Brin...%+27788225528 love spells in Toronto Psychic Readings, Attraction spells,Brin...
%+27788225528 love spells in Toronto Psychic Readings, Attraction spells,Brin...
 
WSO2Con2024 - Enabling Transactional System's Exponential Growth With Simplicity
WSO2Con2024 - Enabling Transactional System's Exponential Growth With SimplicityWSO2Con2024 - Enabling Transactional System's Exponential Growth With Simplicity
WSO2Con2024 - Enabling Transactional System's Exponential Growth With Simplicity
 
%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...
%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...
%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...
 
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...
 
%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 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
 
%in Stilfontein+277-882-255-28 abortion pills for sale in Stilfontein
%in Stilfontein+277-882-255-28 abortion pills for sale in Stilfontein%in Stilfontein+277-882-255-28 abortion pills for sale in Stilfontein
%in Stilfontein+277-882-255-28 abortion pills for sale in Stilfontein
 

Essence of the iterator pattern

  • 2. Goal “Imperative iterations using the pattern have two simultaneous aspects: mapping and accumulating.” Jeremy Gibbons & Bruno C. d. S. Oliveira Markus Klink, @joheinz, markus.klink@inoio.de
  • 3. Functionalmappingand accumulating trait Traverse[F[_]] extends Functor[F] with Foldable[F] { def traverse[G[_]: Applicative, A, B](fa: F[A])(f: A => G[B]): G[F[B]] } trait Applicative[F[_]] extends Functor[F] { def ap[A,B](fa: F[A])(f: F[A => B]) : F[B] def pure(a: A) : F[A] def map[A,B](fa: F[A])(f: A => B) : F[B] = ap(fa)(pure(f)) } Traverse takes a structure F[A], injects each element via the function f: A => G[B] into an Applicative G[_] and combines the results into G[F[B] using the applicative instance of G. Markus Klink, @joheinz, markus.klink@inoio.de
  • 4. Acloser look trait Foldable[F[_]] { def foldRight[A, B](fa: F[A], z: => B)(f: (A, B) => B): B } trait Traverse[F[_]] extends Functor[F] with Foldable[F] { def traverse[G[_]: Applicative, A, B](fa: F[A])(f: A => G[B]): G[F[B]] } Look at the similarities! Markus Klink, @joheinz, markus.klink@inoio.de
  • 5. Traversing is "almost" like Folding: » Look! No zero element: def foldRight[A, B](fa: F[A], z: => B)(f: (A, B) => B): B def traverse[G[_]: Applicative, A, B](fa: F[A])(f: A => G[B]): G[F[B]] » Look! B is wrapped in an Applicative and our F: def foldRight[A, B](fa: F[A], z: => B)(f: (A, B) => B): B def traverse[G[_]: Applicative, A, B](fa: F[A])(f: A => G[B]): G[F[B]] Markus Klink, @joheinz, markus.klink@inoio.de
  • 6. Accumulating Markus Klink, @joheinz, markus.klink@inoio.de
  • 7. val l = List(1,2,3) val result: Future[List[String]] = l.traverse(a => Future.successful { a.toString }) How? // traverse implementation of List, G[_] is the future override def traverse[G[_]: Applicative, A, B](fa: List[A])(f: (A) => G[B]): G[List[B]] = { val emptyListInG: G[List[B]] = Applicative[G].pure(List.empty[B]) // if the list is empty we need a Future { List.empty() } // f(a) gives us another G[B], which we can inject into B => B => Future[List[B]] foldRight(fa, emptyListInG) { (a: A, fbs: G[List[B]]) => Applicative[G].apply2(f(a), fbs)(_ +: _) } } // applicative instance of Future, example... override def ap[A,B](F: => Future[A])(f: => Future[A => B]) : Future[B] = { for { a <- F g <- f } yield { g(a) } } Markus Klink, @joheinz, markus.klink@inoio.de
  • 8. Gibbons & Oliveiraclaimthatwe can do: val x : List[Char]= "1234".toList val result : Int = x.traverse(c => ???) assert(4 == result) The claim is that we can accumulate values, or write the length function just with Traverse/Applicative Markus Klink, @joheinz, markus.klink@inoio.de
  • 9. How? » we need a result type G[List[Int]] which equals Int » G needs to be an applicative » we need to calculate a sum of all the values. » we need a zero value in case the list is empty, because of ... val emptyListInG: G[List[B]] = Applicative[G].pure(List.empty[B]) Markus Klink, @joheinz, markus.klink@inoio.de
  • 10. Each Monoid gives risetoan applicative trait Monoid[F] extends Semigroup[F] { self => /** * the identity element. */ def zero: F def applicative: Applicative[Lambda[a => F]] = new Applicative[Lambda[a => F]] { // mapping just returns ourselves override def map[A, B](fa: F)(f: A => B) : F = fa // putting any value into this Applicative will put the Monoid.zero in it def pure[A](a: => A): F = self.zero // Applying this Applicative combines each value with the append function. def ap[A, B](fa: => F)(f: => F): F = self.append(f, fa) } Markus Klink, @joheinz, markus.klink@inoio.de
  • 11. How2 Part of the trick is this type: Applicative[Lambda[a => F]]! It means that we throw everything away and create a type G[_] which behaves like F. So... val x : List[Char]= "1234".toList val charCounter : Applicative[Lambda[a => Int]] = Monoid[Int].applicative // we just "reversed" the parameters of traverse // the summing is done automatically via append charCounter.traverse(x)(_ => 1) Markus Klink, @joheinz, markus.klink@inoio.de
  • 12. Counting lines In the previous example we assigned each char in the list to a 1 and let the Monoid do the work. val x : List[Char] = "1233n1234n" val lineCounter : Applicative[Lambda[a => Int]] = Monoid[Int].applicative lineCounter.traverse(x){c => if (c == 'n') 1 else 0 } Markus Klink, @joheinz, markus.klink@inoio.de
  • 13. Products ofApplicatives Doing bothatthe sametimewithinasingle traversal val x : List[Char]= "1234n1234n" val counter : Applicative[Lambda[a => Int]] = Monoid[Int].applicative val charLineApp : Applicative[Lambda[a => (Int, Int)]] = counter.product[Lambda[a => Int](counter) val (chars, lines) = counter.traverse(x){c => (1 -> if (c == 'n') 1 else 0 } Markus Klink, @joheinz, markus.klink@inoio.de
  • 14. Countingwords Counting words cannot work on the current position alone. We need to track changes from spaces to non spaces to recognize the beginning of a new word. def atWordStart(c: Char): State[Boolean, Int] = State { (prev: Boolean) => val cur = c != ' ' (cur, if (!prev && cur) 1 else 0) } val WordCount : Applicative[Lambda[a => Int]] = State.stateMonad[Boolean].compose[Lambda[a => Int](counter) val StateWordCount = WordCount.traverse(text)(c => atWordStart(c)) StateWordCount.eval(false) Markus Klink, @joheinz, markus.klink@inoio.de
  • 15. Usingthe productofall3 countersto implementwc val AppCharLinesWord: Applicative[Lambda[a => ((Int, Int), State[Boolean, Int])]] = Count // char count .product[Lambda[a => Int]](Count) // line count .product[Lambda[a => State[Boolean, Int]]](WordCount) // word count val ((charCount, lineCount), wordCountState) = AppCharLinesWord.traverse(text)((c: Char) => ((1, if (c == 'n') 1 else 0), atWordStart(c))) val wordCount: Int = wordCountState.eval(false) Markus Klink, @joheinz, markus.klink@inoio.de
  • 16. Collecting some state and modifying elements Markus Klink, @joheinz, markus.klink@inoio.de
  • 17. // start value public Integer count = 0; public Collection<Person> collection = ...; for (e <- collection) { // or we use an if count = count + 1; // side effecting function // or we map into another collection e.modify(); } Obviously in a functional programming language, we would not want to modify the collection but get back a new collection. We also would like to get the (stateful) counter back. Markus Klink, @joheinz, markus.klink@inoio.de
  • 18. def collect[G[_]: Applicative, A, B](fa: F[A])(f: A => G[Unit])(g: A => B): G[F[B]] = { val G = implicitly[Applicative[G]] val applicationFn : A => G[B] = a => G.ap(f(a))(G.pure((u: Unit) => g(a))) self.traverse(fa)(applicationFn) } def collectS[S, A, B](fa: F[A])(f: A => State[S, Unit])(g: A => B): State[S, F[B]] = { collect[Lambda[a => State[S, a]], A, B](fa)(f)(g) } val list : List[Person] = ... val stateMonad = State.stateMonad[Int] val (counter, updatedList) = list.collectS{ a => for { count <- get; _ <- put(count + 1) } yield ()}(p => p.modify()).run(0) Markus Klink, @joheinz, markus.klink@inoio.de
  • 19. Modifying elements depending on some state Markus Klink, @joheinz, markus.klink@inoio.de
  • 20. // start value public Collection<Person> collection = ...; for (e <- collection) { e.modify(stateful()); } Now the modification depends on some state we are collecting. Markus Klink, @joheinz, markus.klink@inoio.de
  • 21. def disperse[G[_]: Applicative, A, B, C](fa: F[A])(fb: G[B], g: A => B => C): G[F[C]] = { val G = implicitly[Applicative[G]] val applicationFn: A => G[C] = a => G.ap(fb)(G.pure(g(a))) self.traverse(fa)(applicationFn) } def disperseS[S, A, C](fa: F[A])(fb: State[S, S], g: A => S => C) : State[S,F[C]] = { disperse[Lambda[a => State[S, a]], A, S, C](fa)(fb, g) } Markus Klink, @joheinz, markus.klink@inoio.de
  • 22. THANKS Markus Klink, @joheinz, markus.klink@inoio.de