by

Where communities thrive


  • Join over 1.5M+ people
  • Join over 100K+ communities
  • Free without limits
  • Create your own community
People
Repo info
Activity
Fabio Labella
@SystemFw
for control flow, a monad instance on the emitted value is much more convenient: this is what streamly has, but then streamly suffers in the other use case
one under appreciated design decision of fs2 is to separate the two into Stream and Pull (which are related to each other ofc)
where Pull is a monad in the returned type, and can be used for stateful streaming, and Stream is a monad in the emitted type, and can be used for control flow
and conceptually Stream f a = Pull f a ()
when I started with fs2 the existence of both Stream and Pull seemed like a wart (although at the time it was obscured by a bunch of other stuff like Handle), but in truth it's one of the best design decisions of the whole library
Adam Rosien
@arosien
i still don't know anything about Pull. where to start?
Fabio Labella
@SystemFw
my writings have a bunch of long-ish explanations (for lack of a more structured resource, sorry) http://systemfw.org/writings
the tl;dr is that it's a fancy iterator, just built as an algebra rather than side-effecty interface
Adam Rosien
@arosien
thanks
oh, that's interesting, i didn't realize that a lot of the links point back to gitter. great idea!
I also wrote up a thing about Pull
that I think helps drive home the "iterator" aspect
Fabio Labella
@SystemFw

oh, that's interesting, i didn't realize that a lot of the links point back to gitter. great idea!

Eventually I will have to go and do a backup somewhere else, but I dread that time

Adam Rosien
@arosien
ThreadApp, please unroll (this gitter link)
Gavin Bisesi
@Daenyth
fabio needs to hire a gitter assistant to take his conversations and translate to blogs :)
Fabio Labella
@SystemFw
tbh for some things I quite like the conversational format (although others would be better served by a proper exposition)
I worry more about gitter getting shutdown at brief notice
Gavin Bisesi
@Daenyth
I learn and internalize the things I teach better, in conversation, than trying to lecture
At least gitter is indexed on google
Some option to grab archives from there
Fabio Labella
@SystemFw
oh yeah still miles better than the proposed alternatives (which is why I opposed migrating to Discord or Slack)
Nathaniel Fischer
@kag0
https://typelevel.org/cats/datatypes/either.html#solution-2-adts-all-the-way-down talks about error ADTs, what's SOP for common errors that you want to share across modules?
Nick Telford
@nicktelford
Is there anything stopping cats from defining typeclass instances for SeqMap? It's useful for preserving the ordering of the mapping.
Jasper Moeys
@Jasper-M
Is there some well known name for this method foo?
def foo[A, B, C](f: A => B)(g: (A, B) => C): A => C =
  a => g(a, f(a))
Fabio Labella
@SystemFw
@Jasper-M that seems equivalent of Applicative.ap for F = A =>, with uncurrying and tuple == parameter lists
but it's not worth writing it differently than what you have I don't think
you can notice by changing (A, B) => C into A => B => C
then factorising the whole signature into (A => B) => (A => (B => C)) => (A => C)
then abstracting A => into F[_]
F[B] => F[B => C] => F[C]
and then alfa-rename and switch order into
F[A => B] => F[A] => F[B], which is the key signature of the Apply typeclass
Fabio Labella
@SystemFw
for F[E] = E => *
(renamed some type variables for clarity)
Jasper Moeys
@Jasper-M
Thanks! I felt like there had to be some cats concept for this
Fabio Labella
@SystemFw
one of the key soft skills is an eye for spotting F[_] patterns
in particular the starting point could have have swiping f and g and noticing basically (A => B) => (A => C)
that should trigger your functorial warning, since functor, applicative and monad can all be seen to transform things into F[B] => F[C]
although it's easier to rename things to F[A] => F[B] for consistency with the way things are usually written down
map: (A => B) => (F[A] => F[B])
ap: F[A => B] => (F[A] => F[B])
flatMap: (A => F[B]) => (F[A] => F[B])
Jasper Moeys
@Jasper-M

one of the key soft skills is an eye for spotting F[_] patterns

I'll tell that to my manager when he starts about communication and presenting

Fabio Labella
@SystemFw
which also helps with understanding that the real difference between power in the three typeclasses reflects the difference in power between A => B (uneffectful), F[A =>B](effectful but no context sensitivity) and A => F[B] (the effect can depend on the output of the previous computation, since A => F

I'll tell that to my manager when he starts about communication and presenting

ahahhaha :+1:

Adam Rosien
@arosien
traverse: (A => G[B]) => (F[A] => G[F[B]])
(kind of like flatMap wooo)

https://typelevel.org/cats/datatypes/either.html#solution-2-adts-all-the-way-down talks about error ADTs, what's SOP for common errors that you want to share across modules?

i think usually you have a separate ADT that is shared across modules. if you can have direct dependencies, then the upper ADT can refer directly to the module error types. otherwise you can cast or translate the module errors into something like Throwable which the upper ADT wraps

Nathaniel Fischer
@kag0
@arosien thanks, that makes sense. I was thinking of doing the opposite - having service specific errors extend common errors. but that just seemed messy.
Adam Rosien
@arosien
agreed!
you probably don't need it, and it's more complicated, but you could have a typeclass that translates "lower" level errors into a "higher" level error, but that means the higher level error loses information (which may be ok)