SlideShare a Scribd company logo
Streams for
(Co)Free!JohnA. De Goes — @jdegoes
Agenda
» Induction/Coinduction
» Universality of Streams
» Cofree: A Principled Stream
» Challenge
InductionTear downastructureto culminate in
aterminalvalue.
Inductive Programs
Examples
» Parse a config file
» Sort a list
» Send an HTTP response
» Compute the millionth digit of pi
Surprise!
Most(?)BusinessProblemsAre
Coinductive
CoinductionStartfroman initialvalueto build up
an infinite structure.
Coinductive Processes
Examples
» Produce the next state of the UI given a user-
input
» Produce current state of config given update to
config
» Transform stream of requests to responses
» Produce (all) the digits of pi
Programming Languages
Hate Coinduction
But"Reactive"and "Streams"
ByAnyOther Name
Astream isamainstream example ofacoinductive process.
» Data processing
» Web servers
» User-interfaces
» Discrete "FRP"
» So much more...
Streams
✓ Stateful
✓ Incremental computation
✓ Non-termination
✓ Consume & Emit
Streams
Choices, Choices
» Akka Streams
» Java Streams
» Scalaz-Streams
» FS2
» Big Data: Spark, Flink, Pachyderm, Kafka, ad
infinitum...
John's Laws ofClean FunctionalCode
1.Reasonability is directly proportional to totality &
referential-transparency.
2.Composability is inversely proportional to number of data
types.
3.Obfuscation is directly proportional to number of lawless
interfaces.
4.Correctness is directly proportional to degree of
polymorphism.
5.Shoddiness is directly proportional to encapsulation.
6.Volume is inversely proportional to orthogonality.
AkkaStream
akka.stream
AbruptTerminationException AbstractShape ActorAttributes ActorMaterializer
ActorMaterializerSettings AmorphousShape Attributes BidiShape BindFailedException
BufferOverflowException Client ClosedShape ConnectionException DelayOverflowStrategy EagerClose
FanInShape FanInShape10 FanInShape11 FanInShape12 FanInShape13 FanInShape14 FanInShape15
FanInShape16 FanInShape17 FanInShape18 FanInShape19 FanInShape1N FanInShape2 FanInShape20
FanInShape21 FanInShape22 FanInShape3 FanInShape4 FanInShape5 FanInShape6 FanInShape7
FanInShape8 FanInShape9 FanOutShape FanOutShape10 FanOutShape11 FanOutShape12 FanOutShape13
FanOutShape14 FanOutShape15 FanOutShape16 FanOutShape17 FanOutShape18 FanOutShape19 FanOutShape2
FanOutShape20 FanOutShape21 FanOutShape22 FanOutShape3 FanOutShape4 FanOutShape5 FanOutShape6
FanOutShape7 FanOutShape8 FanOutShape9 FlowMonitor FlowMonitorState FlowShape Fusing Graph
IgnoreBoth IgnoreCancel IgnoreComplete Inlet InPort IOResult KillSwitch KillSwitches
MaterializationContext MaterializationException Materializer MaterializerLoggingProvider Outlet
OutPort OverflowStrategy QueueOfferResult RateExceededException Server Shape SharedKillSwitch
SinkShape SourceShape StreamLimitReachedException StreamSubscriptionTimeoutSettings
StreamSubscriptionTimeoutTerminationMode StreamTcpException SubstreamCancelStrategy Supervision
ThrottleMode TLSClientAuth TLSClosing TLSProtocol TLSRole UniformFanInShape UniformFanOutShape
UniqueKillSwitch
WhatCan Save Us?!?
John's Laws ofClean FunctionalCode
1.Reasonability is directly proportional to totality &
referential-transparency.
2.Composability is inversely proportional to number of data
types.
3.Obfuscation is directly proportional to number of lawless
interfaces.
4.Correctness is directly proportional to degree of polymorphism.
5.Shoddiness is directly proportional to encapsulation.
6.Volume is inversely proportional to orthogonality.
CofreeALLTHE POWER OFFREE, NOWWITH
STREAMING!!!
Cofree
Huh?
// For Functor `F`
final case class Cofree[F[_], A](head: A, tail: F[Cofree[F, A]])
Cofree:Take 1Cofree[F,A] isacoinductive process
thatgenerates A's using effect F.
Cofree:Take 2Cofree[F,A] isacurrentposition A ona
landscapethatrequires effect Fto
movetoanewposition.
Cofree
Comonad Methods
» Where am I? def extract(f: Cofree[F, A]): A
» Terraform! def extend(f: Cofree[F, A] => B):
Cofree[F, B]
» Plus Functor!
Cofree
Fibs
final case class Cofree[F[_], A](head: A, tail: F[Cofree[F, A]])
// final case class Name[A](run: => A)
val fibs: Cofree[Name, Int] = {
def unfold(prev1: Int, prev2: Int): Cofree[Name, Int] =
Cofree(prev1 + prev2, Name(unfold(prev2, prev1 + prev2)))
unfold(0, 1)
}
Cofree
Append
def append[F[_]: ApplicativePlus, A](c1: Cofree[F, A], c2: Cofree[F, A]): Cofree[F, A] =
Cofree(c1.head, c1.tail.map(t => append(t, c2)) <+> c2.point[F])
Cofree
Collect/Disperse
def collect[F[_]: MonadPlus, A](c: Cofree[F, A]): F[Vector[A]] = {
val singleton = Vector[A](c.head).point[F]
(singleton |@| c.tail.flatMap(collect(_)))(_ ++ _) <+> singleton
}
def disperse[F[_]: ApplicativePlus, A](seq: Seq[A]): Option[Cofree[F, A]] =
seq.foldRight[Option[Cofree[F, A]]](None) {
case (a, None) => Some(Cofree(a, mempty[F, Cofree[F, A]]))
case (a, Some(tail)) => Some(Cofree(a, tail.point[F]))
}
Cofree
Zip
def zipWith[F[_]: Zip: Functor, A, B, C](
c1: Cofree[F, A], c2: Cofree[F, B])(
f: (A, B) => C): Cofree[F, C] =
Cofree(
f(c1.head, c2.head),
Zip[F].zipWith(c1.tail, c2.tail)(zipWith(_, _)(f)))
Cofree
Scan
def scan[F[_]: Functor, A, S](
c: Cofree[F, A])(s: S)(f: (S, A) => S): Cofree[F, S] = {
val s2 = f(s, c.head)
Cofree(s2, c.tail.map(scan(_)(s2)(f)))
}
Cofree
Filter
def zeros[F[_]: Functor, A: Monoid](c: Cofree[F, A])(p: A => Boolean): Cofree[F, A] =
if (p(c.head)) Cofree(c.head, c.tail.map(zeros(_)(p)))
else Cofree(mzero[A], c.tail.map(zeros(_)(p)))
def filter[F[_]: Monad, A](c: Cofree[F, A])(p: A => Boolean): F[Cofree[F, A]] =
if (p(c.head)) Cofree(c.head, c.tail.flatMap(filter(_)(p))).point[F]
else c.tail.flatMap(filter(_)(p))
Cofree
Pipes:Types
// final case class Kleisli[F[_], A, B](run: A => F[B])
type Pipe[F[_], A, B] = Cofree[Kleisli[F, A, ?], B]
type Source[F[_], A] = Pipe[F, Unit, A]
type Sink[F[_], A] = Pipe[F, A, Unit]
Cofree
Pipes: Utilities
def pipe[F[_]: Applicative, A, B, C](from: Pipe[F, A, B], to: Pipe[F, B, C]): Pipe[F, A, C] =
Cofree[Kleisli[F, A, ?], C](
to.head,
Kleisli(a => (from.tail.run(a) |@| to.tail.run(from.head))(pipe(_, _))))
// e.g. Unit
def runPipe[F[_]: Monad, A: Monoid](pipe: Pipe[F, A, A]): F[A] =
(pipe.head.point[F] |@| pipe.tail.run(mzero[A]).flatMap(runPipe(_)))(_ |+| _)
Cofree
IO, Byte Streams, Etc.
type IOPipe[A, B] = Pipe[Task, A, B]
...
type BytePipe = IOPipe[Array[Byte], Array[Byte]]
Cofree
Merging:Types
type Select[F[_], A] = Coproduct[F, F, A]
type Merge[F[_], A, B] = Pipe[Select[F, ?], A, B]
Cofree
Merging: Function
def merge[F[_]: Applicative, A, B](left: Source[F, A], right: Source[F, A])
(s: Select[Id, Merge[F, A, B]]): Source[F, B] = {
def embed[F[_]: Functor, A](s: Select[F, A]): F[Select[Id, A]] = s.run match {
case -/ (fa) => fa.map(a => Coproduct[Id, Id, A](a.left [A]))
case /-(fa) => fa.map(a => Coproduct[Id, Id, A](a.right[A]))
}
def step(y: Merge[F, A, B], fs: F[Source[F, B]]): Source[F, B] =
Cofree[Kleisli[F, Unit, ?], B](y.head, Kleisli(_ => fs))
s.run match {
case -/ (y) =>
step(y,
(left.tail.run(()) |@| embed(y.tail.run(left.head)))(
(left, y) => merge(left, right)(y)))
case /-(y) =>
step(y,
(right.tail.run(()) |@| embed(y.tail.run(right.head)))(
(right, y) => merge(left, right)(y)))
}
}
Cofree
Forking
def fork[F[_]: Applicative, A](left: Sink[F, A], right: Sink[F, A]): Sink[F, A] =
Cofree[Kleisli[F, A, ?], Unit]((),
Kleisli(a => (left.tail.run(a) |@| right.tail.run(a))(fork(_, _))))
Cofree
Machines
case class Instr[F[_], A](
goLeft: F[A],
goRight: F[A],
goUp: F[A],
goDown: F[A])
// Cofree[Instr[F, ?], A]
def productWith[F[_]: Functor, G[_]: Functor, A, B, C](
c1: Cofree[F, A], c2: Cofree[G, B])(
f: (A, B) => C): Cofree[Product[F, G, ?], C] =
Cofree[Product[F, G, ?], C](f(c1.head, c2.head),
Product((c1.tail.map(productWith(_, c2)(f)),
c2.tail.map(productWith(c1, _)(f)))))
CofreeProduction-Ready?
No, BUT...
ChallengeGo Do SomethingThat'sATinyBit
Simpler...ABitMore Functional...
THANKYOUFollowme onTwitterat@jdegoes

More Related Content

PDF
ZIO Schedule: Conquering Flakiness & Recurrence with Pure Functional Programming
PDF
Post-Free: Life After Free Monads
PDF
Error Management: Future vs ZIO
PDF
MTL Versus Free
PDF
Blazing Fast, Pure Effects without Monads — LambdaConf 2018
PDF
Why The Free Monad isn't Free
PDF
All Aboard The Scala-to-PureScript Express!
PDF
Fun with Kotlin
ZIO Schedule: Conquering Flakiness & Recurrence with Pure Functional Programming
Post-Free: Life After Free Monads
Error Management: Future vs ZIO
MTL Versus Free
Blazing Fast, Pure Effects without Monads — LambdaConf 2018
Why The Free Monad isn't Free
All Aboard The Scala-to-PureScript Express!
Fun with Kotlin

What's hot (20)

PDF
EuroPython 2017 - Bonono - Simple ETL in python 3.5+
PDF
Python Performance 101
PDF
Simple ETL in Python 3.5+ - PolyConf Paris 2017 - Lightning Talk (10 minutes)
PDF
Simple ETL in python 3.5+ with Bonobo - PyParis 2017
PDF
The Next Great Functional Programming Language
PDF
Python Coroutines, Present and Future
PDF
Ray tracing with ZIO-ZLayer
PDF
Ray Tracing with ZIO
PPTX
Scala - where objects and functions meet
PDF
Scalaz Stream: Rebirth
PDF
Apache PIG - User Defined Functions
KEY
Python Yield
ZIP
Intro to Pig UDF
PDF
Scalapeno18 - Thinking Less with Scala
PDF
JVMLS 2016. Coroutines in Kotlin
PDF
Don't do this
PDF
Embedding Generic Monadic Transformer into Scala. [Tfp2022]
PDF
Enterprise Algebras, Scala World 2016
PDF
Docopt
PPTX
05 pig user defined functions (udfs)
EuroPython 2017 - Bonono - Simple ETL in python 3.5+
Python Performance 101
Simple ETL in Python 3.5+ - PolyConf Paris 2017 - Lightning Talk (10 minutes)
Simple ETL in python 3.5+ with Bonobo - PyParis 2017
The Next Great Functional Programming Language
Python Coroutines, Present and Future
Ray tracing with ZIO-ZLayer
Ray Tracing with ZIO
Scala - where objects and functions meet
Scalaz Stream: Rebirth
Apache PIG - User Defined Functions
Python Yield
Intro to Pig UDF
Scalapeno18 - Thinking Less with Scala
JVMLS 2016. Coroutines in Kotlin
Don't do this
Embedding Generic Monadic Transformer into Scala. [Tfp2022]
Enterprise Algebras, Scala World 2016
Docopt
05 pig user defined functions (udfs)
Ad

Viewers also liked (20)

PDF
Origins of free
PDF
The Easy-Peasy-Lemon-Squeezy, Statically-Typed, Purely Functional Programming...
PDF
Getting Started with PureScript
PDF
Halogen: Past, Present, and Future
PDF
Reducing Boilerplate and Combining Effects: A Monad Transformer Example
PDF
Make your programs Free
PPS
Stream of Consciousness lecture
PDF
FP is coming... le 19/05/2016
PDF
Implementing pattern-matching in JavaScript (short version)
PDF
“Going bananas with recursion schemes for fixed point data types”
PPTX
stream of consciousness
PPTX
Running Free with the Monads
PPT
8 River Landforms
PPTX
PDF
Rivers - livelihood
PPT
River erosion and transport
PPTX
Stream of consciousness
PPT
Stages Of A River
PPTX
Stream of consciousness
PDF
Self purification of river-streams
Origins of free
The Easy-Peasy-Lemon-Squeezy, Statically-Typed, Purely Functional Programming...
Getting Started with PureScript
Halogen: Past, Present, and Future
Reducing Boilerplate and Combining Effects: A Monad Transformer Example
Make your programs Free
Stream of Consciousness lecture
FP is coming... le 19/05/2016
Implementing pattern-matching in JavaScript (short version)
“Going bananas with recursion schemes for fixed point data types”
stream of consciousness
Running Free with the Monads
8 River Landforms
Rivers - livelihood
River erosion and transport
Stream of consciousness
Stages Of A River
Stream of consciousness
Self purification of river-streams
Ad

Similar to Streams for (Co)Free! (20)

PDF
Streams for (Co)Free!
PDF
Drinking the free kool-aid
PDF
Scala-Gopher: CSP-style programming techniques with idiomatic Scala.
PDF
Monadologie
PPTX
The Essence of the Iterator Pattern
PDF
The Essence of the Iterator Pattern (pdf)
PDF
Free Based DSLs for Distributed Compute Engines
PDF
Functional Operations - Susan Potter
PDF
Ti1220 Lecture 7: Polymorphism
PDF
Monad Transformers In The Wild
PDF
Concepts of Functional Programming for Java Brains (2010)
PDF
pure-functional-programming.pdf
PDF
Building a Functional Stream in Scala
PDF
Fp in scala part 2
PDF
Comonads in Haskell
PDF
Extensible Effects in Dotty
PDF
How to start functional programming (in Scala): Day1
PDF
Coding in Style
PDF
Scala Functional Patterns
PDF
Fs2 - Crash Course
Streams for (Co)Free!
Drinking the free kool-aid
Scala-Gopher: CSP-style programming techniques with idiomatic Scala.
Monadologie
The Essence of the Iterator Pattern
The Essence of the Iterator Pattern (pdf)
Free Based DSLs for Distributed Compute Engines
Functional Operations - Susan Potter
Ti1220 Lecture 7: Polymorphism
Monad Transformers In The Wild
Concepts of Functional Programming for Java Brains (2010)
pure-functional-programming.pdf
Building a Functional Stream in Scala
Fp in scala part 2
Comonads in Haskell
Extensible Effects in Dotty
How to start functional programming (in Scala): Day1
Coding in Style
Scala Functional Patterns
Fs2 - Crash Course

More from John De Goes (19)

PDF
Refactoring Functional Type Classes
PDF
One Monad to Rule Them All
PDF
Atomically { Delete Your Actors }
PDF
The Death of Final Tagless
PDF
Scalaz Stream: Rebirth
PDF
ZIO Queue
PDF
Scalaz 8: A Whole New Game
PDF
Scalaz 8 vs Akka Actors
PDF
Orthogonal Functional Architecture
PDF
The Design of the Scalaz 8 Effect System
PDF
Quark: A Purely-Functional Scala DSL for Data Processing & Analytics
PPTX
SlamData - How MongoDB Is Powering a Revolution in Visual Analytics
PPTX
The Dark Side of NoSQL
PDF
First-Class Patterns
PDF
Quirrel & R for Dummies
PDF
In-Database Predictive Analytics
PDF
Analytics Maturity Model
PDF
Rise of the scientific database
PDF
Fun with automata
Refactoring Functional Type Classes
One Monad to Rule Them All
Atomically { Delete Your Actors }
The Death of Final Tagless
Scalaz Stream: Rebirth
ZIO Queue
Scalaz 8: A Whole New Game
Scalaz 8 vs Akka Actors
Orthogonal Functional Architecture
The Design of the Scalaz 8 Effect System
Quark: A Purely-Functional Scala DSL for Data Processing & Analytics
SlamData - How MongoDB Is Powering a Revolution in Visual Analytics
The Dark Side of NoSQL
First-Class Patterns
Quirrel & R for Dummies
In-Database Predictive Analytics
Analytics Maturity Model
Rise of the scientific database
Fun with automata

Recently uploaded (20)

PPTX
KOM of Painting work and Equipment Insulation REV00 update 25-dec.pptx
PDF
Approach and Philosophy of On baking technology
PDF
Unlocking AI with Model Context Protocol (MCP)
PDF
Reach Out and Touch Someone: Haptics and Empathic Computing
DOCX
The AUB Centre for AI in Media Proposal.docx
PPTX
Understanding_Digital_Forensics_Presentation.pptx
PDF
Review of recent advances in non-invasive hemoglobin estimation
PDF
7 ChatGPT Prompts to Help You Define Your Ideal Customer Profile.pdf
PDF
CIFDAQ's Market Insight: SEC Turns Pro Crypto
PPTX
A Presentation on Artificial Intelligence
PDF
Blue Purple Modern Animated Computer Science Presentation.pdf.pdf
PPT
Teaching material agriculture food technology
PDF
KodekX | Application Modernization Development
PDF
Chapter 3 Spatial Domain Image Processing.pdf
PDF
Build a system with the filesystem maintained by OSTree @ COSCUP 2025
PDF
Architecting across the Boundaries of two Complex Domains - Healthcare & Tech...
PDF
Building Integrated photovoltaic BIPV_UPV.pdf
PPTX
Effective Security Operations Center (SOC) A Modern, Strategic, and Threat-In...
PDF
Encapsulation_ Review paper, used for researhc scholars
PDF
Per capita expenditure prediction using model stacking based on satellite ima...
KOM of Painting work and Equipment Insulation REV00 update 25-dec.pptx
Approach and Philosophy of On baking technology
Unlocking AI with Model Context Protocol (MCP)
Reach Out and Touch Someone: Haptics and Empathic Computing
The AUB Centre for AI in Media Proposal.docx
Understanding_Digital_Forensics_Presentation.pptx
Review of recent advances in non-invasive hemoglobin estimation
7 ChatGPT Prompts to Help You Define Your Ideal Customer Profile.pdf
CIFDAQ's Market Insight: SEC Turns Pro Crypto
A Presentation on Artificial Intelligence
Blue Purple Modern Animated Computer Science Presentation.pdf.pdf
Teaching material agriculture food technology
KodekX | Application Modernization Development
Chapter 3 Spatial Domain Image Processing.pdf
Build a system with the filesystem maintained by OSTree @ COSCUP 2025
Architecting across the Boundaries of two Complex Domains - Healthcare & Tech...
Building Integrated photovoltaic BIPV_UPV.pdf
Effective Security Operations Center (SOC) A Modern, Strategic, and Threat-In...
Encapsulation_ Review paper, used for researhc scholars
Per capita expenditure prediction using model stacking based on satellite ima...

Streams for (Co)Free!

  • 1. Streams for (Co)Free!JohnA. De Goes — @jdegoes
  • 2. Agenda » Induction/Coinduction » Universality of Streams » Cofree: A Principled Stream » Challenge
  • 4. Inductive Programs Examples » Parse a config file » Sort a list » Send an HTTP response » Compute the millionth digit of pi
  • 6. CoinductionStartfroman initialvalueto build up an infinite structure.
  • 7. Coinductive Processes Examples » Produce the next state of the UI given a user- input » Produce current state of config given update to config » Transform stream of requests to responses » Produce (all) the digits of pi
  • 9. ByAnyOther Name Astream isamainstream example ofacoinductive process. » Data processing » Web servers » User-interfaces » Discrete "FRP" » So much more...
  • 10. Streams ✓ Stateful ✓ Incremental computation ✓ Non-termination ✓ Consume & Emit
  • 11. Streams Choices, Choices » Akka Streams » Java Streams » Scalaz-Streams » FS2 » Big Data: Spark, Flink, Pachyderm, Kafka, ad infinitum...
  • 12. John's Laws ofClean FunctionalCode 1.Reasonability is directly proportional to totality & referential-transparency. 2.Composability is inversely proportional to number of data types. 3.Obfuscation is directly proportional to number of lawless interfaces. 4.Correctness is directly proportional to degree of polymorphism. 5.Shoddiness is directly proportional to encapsulation. 6.Volume is inversely proportional to orthogonality.
  • 13. AkkaStream akka.stream AbruptTerminationException AbstractShape ActorAttributes ActorMaterializer ActorMaterializerSettings AmorphousShape Attributes BidiShape BindFailedException BufferOverflowException Client ClosedShape ConnectionException DelayOverflowStrategy EagerClose FanInShape FanInShape10 FanInShape11 FanInShape12 FanInShape13 FanInShape14 FanInShape15 FanInShape16 FanInShape17 FanInShape18 FanInShape19 FanInShape1N FanInShape2 FanInShape20 FanInShape21 FanInShape22 FanInShape3 FanInShape4 FanInShape5 FanInShape6 FanInShape7 FanInShape8 FanInShape9 FanOutShape FanOutShape10 FanOutShape11 FanOutShape12 FanOutShape13 FanOutShape14 FanOutShape15 FanOutShape16 FanOutShape17 FanOutShape18 FanOutShape19 FanOutShape2 FanOutShape20 FanOutShape21 FanOutShape22 FanOutShape3 FanOutShape4 FanOutShape5 FanOutShape6 FanOutShape7 FanOutShape8 FanOutShape9 FlowMonitor FlowMonitorState FlowShape Fusing Graph IgnoreBoth IgnoreCancel IgnoreComplete Inlet InPort IOResult KillSwitch KillSwitches MaterializationContext MaterializationException Materializer MaterializerLoggingProvider Outlet OutPort OverflowStrategy QueueOfferResult RateExceededException Server Shape SharedKillSwitch SinkShape SourceShape StreamLimitReachedException StreamSubscriptionTimeoutSettings StreamSubscriptionTimeoutTerminationMode StreamTcpException SubstreamCancelStrategy Supervision ThrottleMode TLSClientAuth TLSClosing TLSProtocol TLSRole UniformFanInShape UniformFanOutShape UniqueKillSwitch
  • 14. WhatCan Save Us?!? John's Laws ofClean FunctionalCode 1.Reasonability is directly proportional to totality & referential-transparency. 2.Composability is inversely proportional to number of data types. 3.Obfuscation is directly proportional to number of lawless interfaces. 4.Correctness is directly proportional to degree of polymorphism. 5.Shoddiness is directly proportional to encapsulation. 6.Volume is inversely proportional to orthogonality.
  • 15. CofreeALLTHE POWER OFFREE, NOWWITH STREAMING!!!
  • 16. Cofree Huh? // For Functor `F` final case class Cofree[F[_], A](head: A, tail: F[Cofree[F, A]])
  • 17. Cofree:Take 1Cofree[F,A] isacoinductive process thatgenerates A's using effect F.
  • 18. Cofree:Take 2Cofree[F,A] isacurrentposition A ona landscapethatrequires effect Fto movetoanewposition.
  • 19. Cofree Comonad Methods » Where am I? def extract(f: Cofree[F, A]): A » Terraform! def extend(f: Cofree[F, A] => B): Cofree[F, B] » Plus Functor!
  • 20. Cofree Fibs final case class Cofree[F[_], A](head: A, tail: F[Cofree[F, A]]) // final case class Name[A](run: => A) val fibs: Cofree[Name, Int] = { def unfold(prev1: Int, prev2: Int): Cofree[Name, Int] = Cofree(prev1 + prev2, Name(unfold(prev2, prev1 + prev2))) unfold(0, 1) }
  • 21. Cofree Append def append[F[_]: ApplicativePlus, A](c1: Cofree[F, A], c2: Cofree[F, A]): Cofree[F, A] = Cofree(c1.head, c1.tail.map(t => append(t, c2)) <+> c2.point[F])
  • 22. Cofree Collect/Disperse def collect[F[_]: MonadPlus, A](c: Cofree[F, A]): F[Vector[A]] = { val singleton = Vector[A](c.head).point[F] (singleton |@| c.tail.flatMap(collect(_)))(_ ++ _) <+> singleton } def disperse[F[_]: ApplicativePlus, A](seq: Seq[A]): Option[Cofree[F, A]] = seq.foldRight[Option[Cofree[F, A]]](None) { case (a, None) => Some(Cofree(a, mempty[F, Cofree[F, A]])) case (a, Some(tail)) => Some(Cofree(a, tail.point[F])) }
  • 23. Cofree Zip def zipWith[F[_]: Zip: Functor, A, B, C]( c1: Cofree[F, A], c2: Cofree[F, B])( f: (A, B) => C): Cofree[F, C] = Cofree( f(c1.head, c2.head), Zip[F].zipWith(c1.tail, c2.tail)(zipWith(_, _)(f)))
  • 24. Cofree Scan def scan[F[_]: Functor, A, S]( c: Cofree[F, A])(s: S)(f: (S, A) => S): Cofree[F, S] = { val s2 = f(s, c.head) Cofree(s2, c.tail.map(scan(_)(s2)(f))) }
  • 25. Cofree Filter def zeros[F[_]: Functor, A: Monoid](c: Cofree[F, A])(p: A => Boolean): Cofree[F, A] = if (p(c.head)) Cofree(c.head, c.tail.map(zeros(_)(p))) else Cofree(mzero[A], c.tail.map(zeros(_)(p))) def filter[F[_]: Monad, A](c: Cofree[F, A])(p: A => Boolean): F[Cofree[F, A]] = if (p(c.head)) Cofree(c.head, c.tail.flatMap(filter(_)(p))).point[F] else c.tail.flatMap(filter(_)(p))
  • 26. Cofree Pipes:Types // final case class Kleisli[F[_], A, B](run: A => F[B]) type Pipe[F[_], A, B] = Cofree[Kleisli[F, A, ?], B] type Source[F[_], A] = Pipe[F, Unit, A] type Sink[F[_], A] = Pipe[F, A, Unit]
  • 27. Cofree Pipes: Utilities def pipe[F[_]: Applicative, A, B, C](from: Pipe[F, A, B], to: Pipe[F, B, C]): Pipe[F, A, C] = Cofree[Kleisli[F, A, ?], C]( to.head, Kleisli(a => (from.tail.run(a) |@| to.tail.run(from.head))(pipe(_, _)))) // e.g. Unit def runPipe[F[_]: Monad, A: Monoid](pipe: Pipe[F, A, A]): F[A] = (pipe.head.point[F] |@| pipe.tail.run(mzero[A]).flatMap(runPipe(_)))(_ |+| _)
  • 28. Cofree IO, Byte Streams, Etc. type IOPipe[A, B] = Pipe[Task, A, B] ... type BytePipe = IOPipe[Array[Byte], Array[Byte]]
  • 29. Cofree Merging:Types type Select[F[_], A] = Coproduct[F, F, A] type Merge[F[_], A, B] = Pipe[Select[F, ?], A, B]
  • 30. Cofree Merging: Function def merge[F[_]: Applicative, A, B](left: Source[F, A], right: Source[F, A]) (s: Select[Id, Merge[F, A, B]]): Source[F, B] = { def embed[F[_]: Functor, A](s: Select[F, A]): F[Select[Id, A]] = s.run match { case -/ (fa) => fa.map(a => Coproduct[Id, Id, A](a.left [A])) case /-(fa) => fa.map(a => Coproduct[Id, Id, A](a.right[A])) } def step(y: Merge[F, A, B], fs: F[Source[F, B]]): Source[F, B] = Cofree[Kleisli[F, Unit, ?], B](y.head, Kleisli(_ => fs)) s.run match { case -/ (y) => step(y, (left.tail.run(()) |@| embed(y.tail.run(left.head)))( (left, y) => merge(left, right)(y))) case /-(y) => step(y, (right.tail.run(()) |@| embed(y.tail.run(right.head)))( (right, y) => merge(left, right)(y))) } }
  • 31. Cofree Forking def fork[F[_]: Applicative, A](left: Sink[F, A], right: Sink[F, A]): Sink[F, A] = Cofree[Kleisli[F, A, ?], Unit]((), Kleisli(a => (left.tail.run(a) |@| right.tail.run(a))(fork(_, _))))
  • 32. Cofree Machines case class Instr[F[_], A]( goLeft: F[A], goRight: F[A], goUp: F[A], goDown: F[A]) // Cofree[Instr[F, ?], A] def productWith[F[_]: Functor, G[_]: Functor, A, B, C]( c1: Cofree[F, A], c2: Cofree[G, B])( f: (A, B) => C): Cofree[Product[F, G, ?], C] = Cofree[Product[F, G, ?], C](f(c1.head, c2.head), Product((c1.tail.map(productWith(_, c2)(f)), c2.tail.map(productWith(c1, _)(f)))))