by

Where communities thrive


  • Join over 1.5M+ people
  • Join over 100K+ communities
  • Free without limits
  • Create your own community
People
Repo info
Activity
  • Sep 05 2019 14:43
    @typelevel-bot banned @jdegoes
  • Jan 31 2019 21:17
    codecov-io commented #484
  • Jan 31 2019 21:08
    scala-steward opened #484
  • Jan 31 2019 18:19
    andywhite37 commented #189
  • Jan 31 2019 02:41
    kamilongus starred typelevel/cats-effect
  • Jan 30 2019 00:01
    codecov-io commented #483
  • Jan 29 2019 23:51
    deniszjukow opened #483
  • Jan 29 2019 23:37
  • Jan 29 2019 23:22
  • Jan 29 2019 20:26
    Rui-L starred typelevel/cats-effect
  • Jan 29 2019 18:01
    jdegoes commented #480
  • Jan 29 2019 17:04
    thomaav starred typelevel/cats-effect
  • Jan 28 2019 17:43
    asachdeva starred typelevel/cats-effect
  • Jan 28 2019 07:12
    alexandru commented #480
  • Jan 28 2019 05:45
    codecov-io commented #482
  • Jan 28 2019 05:35
    daron666 opened #482
  • Jan 27 2019 13:56
    codecov-io commented #481
  • Jan 27 2019 13:46
    lrodero opened #481
  • Jan 27 2019 05:47
    codecov-io commented #460
  • Jan 27 2019 05:37
    codecov-io commented #460
Sean Kwak
@cosmir17
Screenshot 2020-06-20 at 18.46.54.png
Hi, I am doing some scala migration work for a non-scala project (weekend hobby). I don't know what to do with the red circled part. I guess I am to use Ref? but even that I don't think it's the right design.
Does Cats effect dev ever create a class including a shared data store?
pool
@hamstakilla
why not Ref tho?
nigredo-tori
@nigredo-tori

@cosmir17, I'd replace a mutable Map with a Ref containing the current state as an immutable Map. But as you said, the whole thing does look messy. Idiomatic FP Scala code tends to emphasize operations over pure data types (case classes and the like) in favor of OOP-style encapsulation of mutable data. So you'd have something like

final case class Board(rowCount: Int, columnCount: Int, grid: Map[Point, GoString[_ <: Player]])
// Some error type you can properly report
final case class IllegalMove(...)
def placeStone[Color <: Player](point: Point, board: Board): Either[InvalidMove, (Board, NeighbourInfo[Color])]
// Same thing, but might be easier to use.
def placeStone[Color <: Player](point: Point): StateT[Either[InvalidMove, *], Board, NeighbourInfo[Color]]

I've gotten rid of parameterization by F here, since it doesn't seem to be necessary.
By the way, parameterizing stuff with Player subtypes looks contrived. It doesn't seem to do anything yet, and it makes expressing certain things difficult. For example, adjacentOppositeColor should actually be a Set[GoString[<opposite of Color>]], but we can't conveniently express that.

Ben Spencer
@dangerousben
@cosmir17 just to double check - does this map actually need to be accessed concurrently? the fact that it was originally just a HashMap kind of implies not?
Sean Kwak
@cosmir17
Thank you @nigredo-tori. I put F there for two reasons.
  1. placeStone operation seems complicated(multiple fold and etc) and will take a long time (around 300ms?).
  2. I am doing it as a practice for Cats effect
Ben Spencer
@dangerousben
if it does though, you could the creation of and access to a ConcurrentHashMap or similar in your Sync effect
Sean Kwak
@cosmir17
@dangerousben It was a python project.
Ben Spencer
@dangerousben
that's quite a lot of code but it looks like it broadly does what I'm talking about
Sean Kwak
@cosmir17
@hamstakilla does Ref natively work for HashMap (or ConcurrentHashMap)?
Can anyone explain why 'https://gist.github.com/johnynek/a8b1a70ebbfaac2836068f8ba3087a72#file-refmap-scala' was written when we can just use Ref? Is it for extra APIs?
Christopher Davenport
@ChristopherDavenport
My MapRef implementation does.
It's nice to be able to work only at the key level without space leaks.
Operations on individual keys get very complicated for atomicity when the same behavior is required for any modifications from a single key.
nigredo-tori
@nigredo-tori

@cosmir17,

placeStone operation seems complicated(multiple fold and etc) and will take a long time (around 300ms?).

Sync.delay is intended to capture side effects. In your original example mutating grid would, indeed, be a side effect. However a CPU-intensive expression is generally not considered a side effect, so you don't have to delay it. If you want to have a tight control over when it gets evaluated, you should look at Eval in Cats instead.

I am doing it as a practice for Cats effect

In my experience, while tagless final approach (parameterizing with F[_]) seems neat, it tends to also introduce unnecessary complexity. Personally, I try to go with concrete types (Either, IO etc.) first, unless I know I will have to mix domains that require different monad capabilities.

Sean Kwak
@cosmir17
@nigredo-tori there is a side effect, mutating the shared map data store from the placestone method
nigredo-tori
@nigredo-tori
@cosmir17, In the original example, yes - and that would indeed necessitate a Sync (or some concrete IO-like type). In the one I proposed above, everything is supposed to be immutable (placeStone produces a separate Board value).
Sorry if that was not clear enough.
Sean Kwak
@cosmir17
@nigredo-tori
  1. it's a practice for Cat effect.
  2. I am migrating a python code. I don't want to change the design. The logic is complicated. I would like to store the state (data store) inside the class

My MapRef implementation does.

@ChristopherDavenport Thank you, I shall read your test class.

Sean Kwak
@cosmir17
Correction* I am migrating a python project
PhillHenry
@PhillHenry
Can I please ask a noddy question?
I get the monad laws and I get that you have to flatMap effects to make them "happen".
What I don't get is: why flatMap? Why can't I, say,. map over an fs2.Stream of effects and have them "executed"? Is the choice of flatMap arbitrary or are there mathematical laws at play here? If so, what are these laws?
Fabio Labella
@SystemFw
@PhillHenry I'm not exactly sure what you mean
ultimately an effect is represented as F[A]
so map: F[A] => (A => B) => F[B] cannot execute further effects in the function simply because there are none there
hence why A => F[B] ,which on more fundamental level, it's the general concept of a continuation when you represents effects in this style (programs as values)
you can have other combinators, but they ultimately resolve to flatmap
e.g. with Stream you have evalMap: Stream[F, A] => (A => F[B) => Stream[F, B]
which is flatMap(a => Stream.eval(f(a))
you can find a similar structure to flatMap in strict side-effecting languages as well, if you squint
Fabio Labella
@SystemFw

i.e. we look at this capability as primitive

val a = readLine
printLine a
a.toUpperCase

but you can construct it as syntactic sugar over snd : a -> b -> b or more generally next: a -> (a -> b) -> b assuming a strict side-effecting language

similarly to how for comprehensions work with flatMap
PhillHenry
@PhillHenry

@SystemFw I guess as a newbie I don't have the mental model. I've learned by rote that one must flatMap but I can see why after years of mapping over Scala collections one might naively think this:

    val printEffect:  Int => IO[Unit]     = x => IO { println(x) }
    val printEach:    Pipe[IO, Int, Unit] = { _.map(x => printEffect(x)) }
    printEach(Stream(1, 2, 3, 4, 5)).compile.toList

prints out the numbers 1 to 5.
It is, of course, wrong. But why (other than "it just is") is currenlty eluding me.
Can you please expand on why A => F[B] is a program and F[A] => (A => B) => F[B] is not?

Fabio Labella
@SystemFw
A => B is not
well, B
your code does not type check
so, the starting point is that println doesn't exist, as you note
println: Unit
what we have is purePrintLn: IO[Unit]
is that clear? (I think it is, but better to check)
@PhillHenry
btw I'm writing a blog post series on the paradigm, from the ground up, which I think will be helpful eventually
PhillHenry
@PhillHenry
Not sure what you mean by "does not type check". Sure, it's a snipped but I'm running it as we speak.
Yes, a "ground up" blog would help enormously. I look forward to it!
Fabio Labella
@SystemFw
you don't have value discard in your options, or the type error will be caught :)
PhillHenry
@PhillHenry
Ah, right! Bad me...
Fabio Labella
@SystemFw
you code compile in the same way as def foo: Unit = 3 does