“A body of running water (such as a river or creek) flowing on earth.”
cat log.txt | uniq
java.io.FileOutputStream
repeat
infinity
evalMap
side effects
merge
concurrency
Stream("Mao", "Popcorn")
.evalMap(meow)
.repeat
.evalMap(eat)
fold
map
filter
collect
evalMap
evalScan
evalFilter
evalTap
merge
zip
append
flatMap
debounce
interruptAfter
groupWithin
delayBy
...or is it?
def eat(cat: String): IO[String] =
IO.println(s"$cat eats.").as(cat)
def nap(cat: String): IO[Unit] =
IO.println(s"$cat naps.")
Stream("Mao", "Popcorn")
.evalMap(eat)
.evalMap(nap)
.repeat
Stream("Mao", "Popcorn")
.evalMap(eat)
.evalMap(nap)
.repeat
1
Mao naps.
Mao eats.
Popcorn naps.
Popcorn eats.
2
Mao eats.
Mao naps.
Popcorn eats.
Popcorn naps.
3
Mao eats.
Popcorn eats.
Mao naps.
Popcorn naps.
“Of or relating to learning”.
“A little learning is a dang'rous thing; Drink deep, or taste not the Pierian spring”
⸺ An Essay on Criticism, Alexander Pope
Pros
Cons
Stream("Mao", "Popcorn")
.evalMap(eat)
.evalMap(nap)
.repeat
Mao eats.
Mao naps.
Popcorn eats.
Popcorn naps.
Pros
Cons
getOrElse(Some("Mao"), "Popcorn") === "Mao"
getOrElse(Some("Mao"), "Popcorn")
Some("Mao") match
case Some(name) => name
case None => "Popcorn"
case Some("Mao") => "Mao"
"Mao"
Stream("Mao", "Popcorn")
.evalMap(eat)
.evalMap(nap)
.repeat
Pull.output(Seq("Mao", "Popcorn")).streamNoScope.underlying
.evalMap(eat)
.evalMap(nap)
.repeat
Pull.output(Seq("Mao", "Popcorn"))
.streamNoScope.underlying
.flatMapOutput(o => Pull.eval(eat(o)).flatMap(Pull.output1))
.streamNoScope.underlying
.evalMap(nap)
.repeat
Pull.output(Seq("Mao", "Popcorn"))
.streamNoScope.underlying
.flatMapOutput(o => Pull.eval(eat(o)).flatMap(Pull.output1))
.streamNoScope.underlying
.flatMapOutput(o => Pull.eval(nap(o)).flatMap(Pull.output1))
.streamNoScope.underlying
.repeat
Pull.output(Seq("Mao", "Popcorn"))
.streamNoScope.underlying
.flatMapOutput(o => Pull.eval(eat(o)).flatMap(Pull.output1))
.streamNoScope.underlying
.flatMapOutput(o => Pull.eval(nap(o)).flatMap(Pull.output1))
.streamNoScope.underlying ++
Pull.output(Seq("Mao", "Popcorn"))
.streamNoScope.underlying
.flatMapOutput(o => Pull.eval(eat(o)).flatMap(Pull.output1))
.streamNoScope.underlying
.flatMapOutput(o => Pull.eval(nap(o)).flatMap(Pull.output1))
.streamNoScope.underlying ++
Pull.output(Seq("Mao", "Popcorn"))
.streamNoScope.underlying
.flatMapOutput(o => Pull.eval(eat(o)).flatMap(Pull.output1))
.streamNoScope.underlying
.flatMapOutput(o => Pull.eval(nap(o)).flatMap(Pull.output1))
.streamNoScope.underlying ++ ...
Pros
Cons
1
s.repeat === s ++ s ++ s ++ ...
2
(s1 ++ s2).evalMap(f) === s1.evalMap(f) ++ s2.evalMap(f)
Prove:
s.repeat.evalMap(eat) === s.evalMap(eat).repeat
mao.repeat.evalMap(eat) === mao.evalMap(eat).repeat
mao.repeat.evalMap(eat)
(mao ++ mao ++ ...).evalMap(eat) // law 1
(mao.evalMap(eat) ++ mao.evalMap(eat) + ...) // law 2
mao.evalMap(eat).repeat // law 1
A monad is just a monoid in the category of endofunctors, what's the problem?
Pros
Cons
Physical analogy
Set of steps
Operators and composition
Predict behaviour
We “pull” on a stream.
An operator: