SlideShare a Scribd company logo
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

More Related Content

What's hot (20)

PDF
Fp in scala with adts part 2
Hang Zhao
 
PDF
10 - Scala. Co-product type (sum type)
Roman Brovko
 
DOCX
CLASS XII COMPUTER SCIENCE MONTHLY TEST PAPER
Rc Os
 
PDF
C programs Set 2
Koshy Geoji
 
PPT
Qno 3 (a)
Praveen M Jigajinni
 
PPTX
statistical computation using R- an intro..
Kamarudheen KV
 
PPT
Qno 2 (c)
Praveen M Jigajinni
 
PDF
Cs practical file
Shailendra Garg
 
PDF
Fp in scala part 1
Hang Zhao
 
PDF
SAMSTAR: A Semi-automated Lexical Method to generate Star Schemas from an ERD
The Children's Hospital of Philadelphia
 
PDF
Modules and Scripts- Python Assignment Help
Anderson Silva
 
PDF
SupportVectorRegression
Daniel K
 
PDF
N-Queens Combinatorial Problem - Polyglot FP for fun and profit - Haskell and...
Philip Schwarz
 
PDF
Matlab integration
pramodkumar1804
 
DOCX
BIometrics- plotting DET and EER curve using Matlab
Shiv Koppad
 
PDF
Monoids - Part 1 - with examples using Scalaz and Cats
Philip Schwarz
 
KEY
An Introduction to Functional Programming using Haskell
Michel Rijnders
 
DOC
Rumus visual basic
T. Astari
 
PPTX
OPERATOR IN PYTHON-PART1
vikram mahendra
 
PDF
Rethinking metrics: metrics 2.0 @ Lisa 2014
Dieter Plaetinck
 
Fp in scala with adts part 2
Hang Zhao
 
10 - Scala. Co-product type (sum type)
Roman Brovko
 
CLASS XII COMPUTER SCIENCE MONTHLY TEST PAPER
Rc Os
 
C programs Set 2
Koshy Geoji
 
statistical computation using R- an intro..
Kamarudheen KV
 
Cs practical file
Shailendra Garg
 
Fp in scala part 1
Hang Zhao
 
SAMSTAR: A Semi-automated Lexical Method to generate Star Schemas from an ERD
The Children's Hospital of Philadelphia
 
Modules and Scripts- Python Assignment Help
Anderson Silva
 
SupportVectorRegression
Daniel K
 
N-Queens Combinatorial Problem - Polyglot FP for fun and profit - Haskell and...
Philip Schwarz
 
Matlab integration
pramodkumar1804
 
BIometrics- plotting DET and EER curve using Matlab
Shiv Koppad
 
Monoids - Part 1 - with examples using Scalaz and Cats
Philip Schwarz
 
An Introduction to Functional Programming using Haskell
Michel Rijnders
 
Rumus visual basic
T. Astari
 
OPERATOR IN PYTHON-PART1
vikram mahendra
 
Rethinking metrics: metrics 2.0 @ Lisa 2014
Dieter Plaetinck
 

Viewers also liked (8)

KEY
Matuura cpp
matuura_core
 
KEY
Objc lambda
matuura_core
 
PDF
SPL fukuokaphp_1
ichikaway
 
KEY
連邦の白いヤツ 「Objective-C」
matuura_core
 
PPTX
Chakkason.pptx
Kenji Imasaki
 
PDF
型! 型!
真一 北原
 
PPTX
The Essence of the Iterator Pattern
Eric Torreborre
 
PDF
Iterator Pattern
melbournepatterns
 
Matuura cpp
matuura_core
 
Objc lambda
matuura_core
 
SPL fukuokaphp_1
ichikaway
 
連邦の白いヤツ 「Objective-C」
matuura_core
 
Chakkason.pptx
Kenji Imasaki
 
型! 型!
真一 北原
 
The Essence of the Iterator Pattern
Eric Torreborre
 
Iterator Pattern
melbournepatterns
 
Ad

Similar to Essence of the iterator pattern (20)

PDF
Sequence and Traverse - Part 3
Philip Schwarz
 
PDF
The Essence of the Iterator Pattern (pdf)
Eric Torreborre
 
PDF
Traversals for all ocasions
Luka Jacobowitz
 
PPTX
Running Free with the Monads
kenbot
 
ODP
Functional Programming With Scala
Knoldus Inc.
 
ODP
Functional programming with Scala
Neelkanth Sachdeva
 
PDF
Oh, All the things you'll traverse
Luka Jacobowitz
 
PDF
Sequence and Traverse - Part 2
Philip Schwarz
 
PDF
Monads and Monoids by Oleksiy Dyagilev
JavaDayUA
 
PDF
Fp in scala part 2
Hang Zhao
 
PDF
Building a Functional Stream in Scala
Derek Wyatt
 
PDF
Monad Transformers - Part 1
Philip Schwarz
 
PDF
How to start functional programming (in Scala): Day1
Taisuke Oe
 
PDF
Demystifying functional programming with Scala
Denis
 
PDF
High Wizardry in the Land of Scala
djspiewak
 
PPT
Functional programming with_scala
Raymond Tay
 
PPTX
Introduction to Monads in Scala (2)
stasimus
 
PDF
Introduction à Scala - Michel Schinz - January 2010
JUG Lausanne
 
PDF
Scala collections
Inphina Technologies
 
PDF
Scala Collections
Meetu Maltiar
 
Sequence and Traverse - Part 3
Philip Schwarz
 
The Essence of the Iterator Pattern (pdf)
Eric Torreborre
 
Traversals for all ocasions
Luka Jacobowitz
 
Running Free with the Monads
kenbot
 
Functional Programming With Scala
Knoldus Inc.
 
Functional programming with Scala
Neelkanth Sachdeva
 
Oh, All the things you'll traverse
Luka Jacobowitz
 
Sequence and Traverse - Part 2
Philip Schwarz
 
Monads and Monoids by Oleksiy Dyagilev
JavaDayUA
 
Fp in scala part 2
Hang Zhao
 
Building a Functional Stream in Scala
Derek Wyatt
 
Monad Transformers - Part 1
Philip Schwarz
 
How to start functional programming (in Scala): Day1
Taisuke Oe
 
Demystifying functional programming with Scala
Denis
 
High Wizardry in the Land of Scala
djspiewak
 
Functional programming with_scala
Raymond Tay
 
Introduction to Monads in Scala (2)
stasimus
 
Introduction à Scala - Michel Schinz - January 2010
JUG Lausanne
 
Scala collections
Inphina Technologies
 
Scala Collections
Meetu Maltiar
 
Ad

Recently uploaded (20)

PPTX
Home Care Tools: Benefits, features and more
Third Rock Techkno
 
PDF
vMix Pro 28.0.0.42 Download vMix Registration key Bundle
kulindacore
 
PDF
Driver Easy Pro 6.1.1 Crack Licensce key 2025 FREE
utfefguu
 
PPTX
Help for Correlations in IBM SPSS Statistics.pptx
Version 1 Analytics
 
PPTX
ChiSquare Procedure in IBM SPSS Statistics Version 31.pptx
Version 1 Analytics
 
PDF
iTop VPN With Crack Lifetime Activation Key-CODE
utfefguu
 
PDF
SciPy 2025 - Packaging a Scientific Python Project
Henry Schreiner
 
PDF
Odoo CRM vs Zoho CRM: Honest Comparison 2025
Odiware Technologies Private Limited
 
PPTX
Agentic Automation Journey Series Day 2 – Prompt Engineering for UiPath Agents
klpathrudu
 
PDF
Online Queue Management System for Public Service Offices in Nepal [Focused i...
Rishab Acharya
 
PDF
Thread In Android-Mastering Concurrency for Responsive Apps.pdf
Nabin Dhakal
 
PDF
IDM Crack with Internet Download Manager 6.42 Build 43 with Patch Latest 2025
bashirkhan333g
 
PDF
Wondershare PDFelement Pro Crack for MacOS New Version Latest 2025
bashirkhan333g
 
PPTX
Tally_Basic_Operations_Presentation.pptx
AditiBansal54083
 
PDF
Revenue streams of the Wazirx clone script.pdf
aaronjeffray
 
PDF
HiHelloHR – Simplify HR Operations for Modern Workplaces
HiHelloHR
 
PPTX
Agentic Automation Journey Session 1/5: Context Grounding and Autopilot for E...
klpathrudu
 
PPTX
In From the Cold: Open Source as Part of Mainstream Software Asset Management
Shane Coughlan
 
PDF
Why Businesses Are Switching to Open Source Alternatives to Crystal Reports.pdf
Varsha Nayak
 
PDF
Open Chain Q2 Steering Committee Meeting - 2025-06-25
Shane Coughlan
 
Home Care Tools: Benefits, features and more
Third Rock Techkno
 
vMix Pro 28.0.0.42 Download vMix Registration key Bundle
kulindacore
 
Driver Easy Pro 6.1.1 Crack Licensce key 2025 FREE
utfefguu
 
Help for Correlations in IBM SPSS Statistics.pptx
Version 1 Analytics
 
ChiSquare Procedure in IBM SPSS Statistics Version 31.pptx
Version 1 Analytics
 
iTop VPN With Crack Lifetime Activation Key-CODE
utfefguu
 
SciPy 2025 - Packaging a Scientific Python Project
Henry Schreiner
 
Odoo CRM vs Zoho CRM: Honest Comparison 2025
Odiware Technologies Private Limited
 
Agentic Automation Journey Series Day 2 – Prompt Engineering for UiPath Agents
klpathrudu
 
Online Queue Management System for Public Service Offices in Nepal [Focused i...
Rishab Acharya
 
Thread In Android-Mastering Concurrency for Responsive Apps.pdf
Nabin Dhakal
 
IDM Crack with Internet Download Manager 6.42 Build 43 with Patch Latest 2025
bashirkhan333g
 
Wondershare PDFelement Pro Crack for MacOS New Version Latest 2025
bashirkhan333g
 
Tally_Basic_Operations_Presentation.pptx
AditiBansal54083
 
Revenue streams of the Wazirx clone script.pdf
aaronjeffray
 
HiHelloHR – Simplify HR Operations for Modern Workplaces
HiHelloHR
 
Agentic Automation Journey Session 1/5: Context Grounding and Autopilot for E...
klpathrudu
 
In From the Cold: Open Source as Part of Mainstream Software Asset Management
Shane Coughlan
 
Why Businesses Are Switching to Open Source Alternatives to Crystal Reports.pdf
Varsha Nayak
 
Open Chain Q2 Steering Committee Meeting - 2025-06-25
Shane Coughlan
 

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, [email protected]
  • 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, [email protected]
  • 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, [email protected]
  • 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, [email protected]
  • 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, [email protected]
  • 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, [email protected]
  • 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, [email protected]
  • 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, [email protected]
  • 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, [email protected]
  • 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, [email protected]
  • 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, [email protected]
  • 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, [email protected]
  • 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, [email protected]
  • 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, [email protected]
  • 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, [email protected]
  • 19. Modifying elements depending on some state Markus Klink, @joheinz, [email protected]
  • 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, [email protected]
  • 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, [email protected]