by

Where communities thrive


  • Join over 1.5M+ people
  • Join over 100K+ communities
  • Free without limits
  • Create your own community
People
Activity
  • 06:12
    retronym edited #9153
  • 06:09
    retronym review_requested #9153
  • 06:09
    retronym edited #9153
  • 06:09
    scala-jenkins milestoned #9153
  • 06:09
    retronym opened #9153
  • 05:27
    diggzhang commented #1752
  • 05:19
    diggzhang synchronize #1752
  • 01:11

    SethTisue on 2.13.x

    fork bijection for JDK 14 compat (compare)

  • Aug 05 21:58
    som-snytt synchronize #7785
  • Aug 05 21:53
    som-snytt commented #7785
  • Aug 05 21:51
    som-snytt commented #7785
  • Aug 05 20:09
    som-snytt commented #7785
  • Aug 05 20:08
    som-snytt commented #7785
  • Aug 05 19:22

    SethTisue on 2.13.x

    upgrade JLine to 3.16.0 (was 3.… Merge pull request #9151 from S… (compare)

  • Aug 05 19:22
    SethTisue closed #9151
  • Aug 05 17:32

    SethTisue on 2.13.x

    2.13: reinstate scalafix, add t… (compare)

  • Aug 05 17:32
    SethTisue closed #1193
  • Aug 05 17:10
    SethTisue commented #1193
  • Aug 05 17:08
    SethTisue commented #1193
  • Aug 05 17:07
    SethTisue commented #1193
Jan Ypma
@jypma
For functional effect systems, I like how ZIO has modelled an "environment", which can represent e.g. a logging output. https://zio.github.io/zio-logging/docs/overview/overview_index.html provides an example for this.
Seth Tisue
@SethTisue
@Daenyth on 2.12 I think you need silencer for that
Gavin Bisesi
@Daenyth
that's what I thought. Oh well
D Cameron Mauch
@DCameronMauch
Is it considered “functional” to have a method that takes state as input and mutates that state? But itself has no internal state and only operates on it’s arguments. It seems like it should be at least referentially transparent. An example would be a method that takes a dB connection, and an ID, then returns something like Option[User] for that ID. Given a dB in a specific state, and the same ID, it will always produce the same output.
I was thinking that if I initialize all my IO kinda stuff, like dB connections, SparkSession, HTTP client, etc in the main and pass that down the call chain, then everything else in the code base can be pure. And I can use testing versions of all these things for testing.
Gavin Bisesi
@Daenyth

mutates that state

Only if you return the mutated state.

If these two programs mean different things, then it's not functional:

val x = theFunction(state, input)
val y = theFunction(state, input)
(x, y)

val z = theFunction(state, input)
(z, z)

// (x, y) === (z, z)

I was thinking that if I initialize all my IO kinda stuff, like dB connections, SparkSession, HTTP client, etc in the main and pass that down the call chain

That is the way to do functional data sharing. Shared data = shared call stack. cats-effect IOApp is very handy for this, as well as Resource

Given a dB in a specific state, and the same ID, it will always produce the same output.

That's not the property that matters for functional programming. FP is about referential transparency, which means an expression in code is equivalent to the result of the expression

D Cameron Mauch
@DCameronMauch
In the case of a method that adds a user for example, the return type would likely be unit.
I’m not sure value of returning something like the dB connection
As it mutated either way
Because it’s “value” is basically all the data that can be queried from the dB
And if the operation changed the data in the dB...
Gavin Bisesi
@Daenyth
The way this works with things that have side effects is that you operate in some kind of context, like the IO type, which preserves that property. The IO value builds up a description of some computation you want to perform (which may have side effects like printing, reading, writing, getting time, using randomness, etc). The description (the IO value) is pure, and you manipulate it with combinators like map and flatMap, to ultimately get one final IO which is your entire application. Then the main function discharges it impurely, and evaluates it (IOApp does this)
Ethan
@esuntag
Functional effect systems are designed to handle that in a referentially transparent way. IO[Unit] is a type that represents an action that will when run do something side effecting
Gavin Bisesi
@Daenyth
Right, as a rule of thumb: in FP, a type signature of A => Unit has only one possible implementation: _ => ()
I gave a tech talk that's aimed at developers new to these concepts and tools. Slides+Video link here: https://github.com/daenyth/intro-cats-effect/
D Cameron Mauch
@DCameronMauch
right, so it’s not really referentially transparent, because the execution of the code != the produced value (unit), correct?
equality meaning interchangability
dang
well, at least I saw ZIO 1.0 was just released
Gavin Bisesi
@Daenyth
The big reason to do things functionally using some IO type like that is that you gain the ability to apply local reasoning, and use equational reasoning.
You can look at code, without any other part of the codebase and know what it means, and know it always means that
If you know the meaning of two expressions, then you know, for free, that the meaning of composing those expressions is the two meanings composed

right, so it’s not really referentially transparent, because the execution of the code != the produced value (unit), correct?

Right, RT is a property of expressions in code

ZIO works on similar principles to cats-effect. The ecosystem for cats-effect IO is richer, and the community is very welcoming.
D Cameron Mauch
@DCameronMauch
I just liked the dependency injection part of ZIO
Gavin Bisesi
@Daenyth
(cats-effect also provides interop interfaces which libraries can use to support IO as well as anything compatible with it, zio included)
I do think that's their most compelling aspect. I haven't seen how it plays out in practice when used idiomatically through a codebase. The approach I take, which has worked very well for me, is to pass dependencies to the constructor of my interface implementations. Mostly this boils down to my main area doing a lot of resource setup, and instantiating implementations, then invoking the overall run method once it's set up
At risk of being dramatic, I wouldn't quite bet on zio at the moment, given that using it might result in team members being forced to interact with some folks who have really been toxic to the scala community at large (as well as others). I've had that stance for a while and recent events have really only reinforced it. If you have no context for all that, then that's probably for the best :)
D Cameron Mauch
@DCameronMauch
I’ve heard rumblings, but kept out of it. Seems weird to me, because I have physically met and spoke with at least one of these main figures, and they seemed pretty agreeable to me. But that is a valid point I had not considered.
Gavin Bisesi
@Daenyth

Seems weird to me, because I have physically met and spoke with at least one of these main figures, and they seemed pretty agreeable to me

Yes, the problematic behaviors are more generally restricted toward people who are collaborators rather than learners. But multiple people have been left the community over those behaviors, and there's sadly a long history of the same going back to pre-scala days

felher
@felher

For me, the main reason to check out ZIO were the typed errors. If someone hasn't used various functional IO systems before but has written quite a bit of Java, I think one's stance on java checked exceptions isn't too bad a proxy. If you think they are evil incarnate, Cats is definitely the way to go. If you think they are a godsend and you're not sure how to ever model your java code otherwise, try out ZIO. And if you think they are kind of okay, but too boilerplatey, don't compose well, ... you're basically in the middle. ZIO's approach to errors might or might not suit you.

There are, of course, a couple of other proxies. Your stance on Typeclasses/FP together with variance, for example.

The dependency injection aspect is interesting too, but wasn't there when I first checked it out and to be honest, as @Daenyth said, I didn't find those too hard to manage in an FT style codebase with Cats-Effect either.

Gavin Bisesi
@Daenyth
I think checked exceptions are actually a poor comparison, because they're bad for a different reason
checked exceptions are great but the problem is that they don't compose, and you have no way to abstract

Contrast with a typed error value channel, which doesn't have that problem.

That said I don't find IO's lack of typed errors a barrier, at all. Even when I do provide typed errors you need to put in fallback handling for the myriad awful ways real things can fail

I think once the design space for typed errors is explored better, we'll have a better sense as a community of what to expect from libraries
Rob Norris
@tpolecat
I model checked exceptions as IO[Either[Failure, A]], unchecked as IO[A]. The difference is in whether I expect the caller to handle the failure.
This works well for me.
Or more generally some abstract F instead of IO.
felher
@felher
Yeah, that's what I do too when working with FT+cats effect.
felher
@felher
And I think if someone is happy with that, there is one less (big) reason to try ZIO.
William Turner
@willtrnr
In Cats I'm looking for something like fromOptionF(fa: F[Option[A]], ifEmpty: => E): F[A] assuming MonadError[F, E]
I currently have exactly that as an implicit extension since I couldn't find a good candidate, so I'm wondering if I just missed it
Luis Miguel Mejía Suárez
@BalmungSan
I am pretty sure that exists
Oh wait, I believe the one that exists takes a plain Option.
So you have to flatMap it.
William Turner
@willtrnr
Yeah my trivial definition is F.flatMap(fa)(F.fromOption(_, ifEmpty))
Luis Miguel Mejía Suárez
@BalmungSan
Ah, then no.
Luis Miguel Mejía Suárez
@BalmungSan

Hi all, I have this problem.

I have to implement this signature:

def collectAs[C, A](sa: fs2.Stream[F, A])(factory: Factory[A, C]): F[C] =

But fs2 will only let me do this:

def collectAsImpl[C[_], A](sa: Stream[F, A])(factory: Factory[A, C[A]]): F[C[A]] =
  sa.compile.to(factory)

So I end up doing this:

collectAsImpl[C1 forSome { type C1[x] }, A](sa)(factory).asInstanceOf[F[C]]

Which works and as far as I can tell is safe.
But looks horrible.

Is there a better way?

Dermot Haughey
@hderms
can someone explain what I'm doing wrong here. I'm mega confused https://scastie.scala-lang.org/9Icd82s6SoaifhEFJdeCbw
nvm I got it
Enrique Mandujano
@EnriqueM_gitlab
"while" loop check condition before iteration of the loop, it means that after first iteration "j == n" because of "j=j+1" so it breaks the embeeded while loop.