Where communities thrive


  • Join over 1.5M+ people
  • Join over 100K+ communities
  • Free without limits
  • Create your own community
People
Repo info
Activity
  • Feb 01 10:11
    @SystemFw banned @Hudsone_gitlab
  • Jan 31 2019 04:19
    404- forked
    404-/fs2
  • Jan 31 2019 03:01
    SethTisue commented #1232
  • Jan 30 2019 17:22
  • Jan 30 2019 13:45
  • Jan 30 2019 10:48
    pchlupacek commented #1406
  • Jan 30 2019 10:47
    pchlupacek commented #1406
  • Jan 30 2019 10:39
    pchlupacek commented #1407
  • Jan 30 2019 09:58
    lJoublanc commented #870
  • Jan 30 2019 09:42
    vladimir-popov commented #1407
  • Jan 30 2019 08:10
    vladimir-popov closed #1407
  • Jan 30 2019 08:10
    vladimir-popov commented #1407
  • Jan 29 2019 19:20
    SystemFw commented #1407
  • Jan 29 2019 19:20
    SystemFw commented #1407
  • Jan 29 2019 18:57
    SystemFw commented #1406
  • Jan 29 2019 17:47
    pchlupacek commented #1406
  • Jan 29 2019 17:42
    pchlupacek commented #1406
  • Jan 29 2019 17:39
    pchlupacek commented #1407
  • Jan 29 2019 17:39
    vladimir-popov edited #1407
  • Jan 29 2019 17:38
    vladimir-popov commented #1406
PhillHenry
@PhillHenry
Thanks. It's only a small project so upgrading to 2.12 is painless.
Andrey
@404-

btw, i spoke to soon earlier. as i said, i wanted:

the resulting stream of pairs to terminate only when both input streams terminate

so, i had to use zipWithPrevious at which point it got pretty gnarly...

val nums  = Stream.range[IO](1, 10).metered(25.millis)
val chars = Stream.range[IO]('a', 'z' + 1).map(_.toChar).metered(10.millis)

type PrevCurr[A] = (Option[A], Option[A])
def noneTermAndZipWithPrev[A]: Pipe[IO, A, PrevCurr[A]] = _
  .noneTerminate
  .zipWithPrevious
  .map { case (prev, curr) => prev.flatten -> curr }

def combine[A, B]: (PrevCurr[A], PrevCurr[B]) => Option[(A, B)] = {
  case ((_, Some(aCurr)), (_, Some(bCurr))) => (aCurr -> bCurr).some
  case ((_, Some(aCurr)), (Some(bPrev), None)) => (aCurr -> bPrev).some
  case ((Some(aPrev), None), (_, Some(bCurr))) => (aPrev -> bCurr).some
  case ((_, None), (_, None)) => None
}

val zipped = for {
  a <- nums.through(noneTermAndZipWithPrev).hold(none[Long] -> 1L.some)
  b <- chars.through(noneTermAndZipWithPrev).hold(none[Char] -> '\0'.some)
  c <- (a, b).mapN(combine).discrete.unNoneTerminate
} yield c
any advice on making that look more sane/pretty?
Gavin Bisesi
@Daenyth
hide it inside a def zipLatest(as: Stream[F, A], bs: Stream[F, B]): Stream[F, (A, B)]
sprinkle with comments :P
Andrey
@404-
i was afraid you'd say that
out of curiosity: is there something to "unzip" a single Stream of pairs with?
def unzip[F[_], A, B]: Pipe[F, (A, B), (Stream[F, A], Stream[F, B])] = ???
Gavin Bisesi
@Daenyth
You probably want evalTap or observe instead
combined with collect
There are some new broadcast / pubsub things I haven't explored much
I think there's a "fan-out" style broadcast thing you could use with collect to implement your unzip
note of course that a simple implementation will lock the two output streams to the same speed
either that or some about of buffering
Fabio Labella
@SystemFw
just know that this style based on fanning out and in is not super idiomatic in fs2
it's mostly seen from people coming from akka-streams, before they fully get the hang of the fs2 philosophy, with its tradeoffs
Andrey
@404-
is that related to the lazy/pull-based nature of fs2?
or is it a difference in design/philosophy?
Fabio Labella
@SystemFw
difference in design, mostly (but not entirely) orthogonal to push vs pull based
Fabio Labella
@SystemFw

lazy/pull-based

Also make sure you don't get things mixed up: some people say that fs2 is "lazy" to mean it's pure, others to mean it's pull based. Both these things are true but they are not the same thing

Andrey
@404-
hmm, doesn't laziness imply a pull-based nature?
Fabio Labella
@SystemFw
wdym by laziness?
:)
purity?
Andrey
@404-
hmm i guess i'm talking about lazy evaluation?
Fabio Labella
@SystemFw
I think you're talking about purity
which in scala is often conflated with lazy evaluation
Andrey
@404-
well, purity is ability to reason about functions without worrying about side effects, no?
Fabio Labella
@SystemFw
nope
Andrey
@404-
i thought purity is achieved through referential transparency
purity is referential transparency (at least in this circle)
Andrey
@404-
right. "not worrying about side effects" is obtained by "suspending" them
Fabio Labella
@SystemFw
that's not false, but it's not what I suggest as the way of looking at things
Andrey
@404-
which i always thought of as "encapsulation"
Fabio Labella
@SystemFw
although unfortunately scala really wants you to think that way
Andrey
@404-
how do you recommend to look at fs2?
Fabio Labella
@SystemFw
this comes before fs2
it goes down to pure fp in general, and cats-effect specifically
btw nothing of what you are saying is strictly incorrect, I want to make this clear
and furthermore, as I said, scala really wants you to mix these concepts together, which is why understanding can be clouded
but I can try and explain as best as I can
Andrey
@404-
:thumbsup:
Fabio Labella
@SystemFw
let's do a small thought experiment: imagine cats-effect was in stdlib, and interop with java didn't exist
furthermore, everything that would otherwise be side-effectful already comes wrapped in IO by the language
you don't have access to F.delay (or async or the rest of the FFI)
does that make sense so far?
Andrey
@404-
hmm so basically "main" is IOApp's "run"?
and access to external world - file system and network - already serves up IOs
Fabio Labella
@SystemFw
yes
Andrey
@404-
sure. makes sense