Where communities thrive


  • Join over 1.5M+ people
  • Join over 100K+ communities
  • Free without limits
  • Create your own community
People
Repo info
Activity
Wilber Chao
@cecol
Is there any article talks about the motivation of trait Apply[F[_]] ?
I wonder that how people come up with the idea of Apply.
Roman Tkalenko
@tkroman

Managed to shave off outer Evals, doesn't look like I lose non-strictness here

def loeb[F[_]: Functor, A](x: F[Eval[F[Eval[A]]] => Eval[A]]): F[Eval[A]] = {
  x.fmap(a => a(Later(loeb(x))))
}

probably can't get simpler than this? since this is self-referential, i can't avoid both accepting and returning evals like this, which is as close (or as far) from haskell as i can get

Wilber Chao
@cecol
Like Functor, Monad, and Applicative they have category theory explanation in papers
Lawrence Wagerfield
@ljwagerfield

Given a Monad[A] how can I create an "empty" instance of A?

For example, if A is List, I'd like a List() as a result.

I've looked at .unit but that returns List(())...

Andi Miller
@andimiller
not everything with a Monad can be empty
you probably want a Monoid
Fabio Labella
@SystemFw
or Alternative/MonoidK if you want it for things of kind * -> * (F[_])
Lawrence Wagerfield
@ljwagerfield
Thanks!
Is there something already in Cats that provides the following function?
def foldLeft[F[_], A, B](values: F[A], seed: B)(fold: (B, A) => B)(implicit monad: Monad[F], monoid: Monoid[F[B]]): F[B] = {
    var accumulation = seed
    val work =
      monad.flatMap(values) { value =>
        accumulation = fold(accumulation, value)
        monoid.empty
      }

    monoid.combine(work, monad.pure(accumulation))
  }
Andi Miller
@andimiller
foldMap I think?
although it's output isn't inside F
Lawrence Wagerfield
@ljwagerfield
correct -- I need it to work on List and fs2.Stream, hence needing the result to be wrapped in an F. I see that Stream does not implement Foldable for this reason (as the result would need to be a single-element stream, not a B). However, since List and fs2.Stream both implement Monad and Monoid, the above function works. It probably breaks all kinds of laws, but just wondering if there's something equivalent already?
Fabio Labella
@SystemFw
curiosity, why do you need to have it work on List as well, as opposed to Stream[Pure, A]?
Lawrence Wagerfield
@ljwagerfield
we're half-way through migrating some code from List to Stream
Fabio Labella
@SystemFw
ah, I see
Yeshwanth Kumar
@morpheyesh
Hello, I am trying to run a simple Free program and below is the code of a program which uses two different algebras - my target monad is EitherT[Future, A, B]. How do I lift the EitherT to Free in my second instruction in for comprehension? ie: I want to perform a logic and return Left and short-circuit the program.

  def test(implicit U: UserRepoSC[SampleApp], I: ImageRepoSC[SampleApp]): Free[SampleApp, String] = {
    import U._
    import I._
    for {
      u <- findUserI("001")
      _ <- EitherT.leftT[Future, String]("err")  //Free.liftT would work?
      _ <- getImageI("002")
    } yield {
      print(u)
      u.get.name
    }
  }

 test.foldMap(sampleApp)
Note: I am using Either Transformer to deal with Future returning APIs. Not sure if thats a right way but seem to work.
Arnau Abella
@monadplus
@morpheyesh How's your SampleApp definition ?
Yeshwanth Kumar
@morpheyesh
SampleApp is a EitherK (Coproduct) of two interpreters.
Arnau Abella
@monadplus
Then you should inject it on one of your algebras, not lift it
I think it's Free.inject but just check it (disclaimer: I have little experience with free)
Yeshwanth Kumar
@morpheyesh

I already do this , these are smart constructors

    implicit def UserRepoSC[F[_]](implicit I: InjectK[UserRepoAlg, F]): UserRepoSC[F] = new UserRepoSC[F]


    class ImageRepoSC[F[_]](implicit I: InjectK[ImageRepoAlg, F]) {
      def getImageI(id: String) = Free.inject[ImageRepoAlg, F](GetImage(id))
    }

    // We need this implicit to convert to the proper instance when required
    implicit def ImageRepoSC[F[_]](implicit I: InjectK[ImageRepoAlg, F]): ImageRepoSC[F] = new ImageRepoSC[F]

  }

But my understanding is till limited.

ah, makes sense. I tried inject and didnt make it to work. will give it a try again @monadplus
Arnau Abella
@monadplus
:+1:
Blaž Marinović
@bmarinovic

I have a bit silly question and I'm not sure I'll explain it well. So I had the discussion with my F# friend the other day, and while he likes the FP, he doesn't do pure FP. So I tried to explain him referential transparency and IO monad. He said that in F# you can easily convert code block to function/lazy-value by adding parentheses to variable. So this:

let a = 
    let read = readline()
    logReading(read)
    printTimeOfDay()
    read

Becomes:

let a() = 
    let read = readline()
    logReading(read)
    printTimeOfDay()
    read

I guess that now you have RT because everywhere where you use a(), you can "swap" it with its chunk of code block - both ways whole code block will be executed every time (not just returning read).
So since you can do same thing in Scala by making every function accept call-by-name arguments, can we call that kind of programming "pure FP" if we are disciplined and keep away from mutating class' fields? Instead of flatMaping, we would have compose and/or our code would start to look like f(g(h(j(x)))), but I guess it's valid.
Anyway, I started to ask myself the benefits of IO data structure. I can name a few: you can have whole range of "helper" methods on IO object (map, flatMap, traverse, ...) which you simply don't have on Function; you structure you code more-or-less sequentially due to Monad nature (although you have sequential code in f(g(x)) case too). When it come to mutation, you still have to be disciplined, nothing prevents you from cheating and mutating some field in your IO.flatMap.
I guess my question is: what are (all) the benefits of IO, especially compared to Function since both can be looked in a way as description of computation?

Rob Norris
@tpolecat
I don't have time to get into a discussion right now but I think it's misleading to frame IO in terms of evaluation semantics. With the code above if you had (a(), a()) and substituted val b = a(); (b, b) it would no longer be the same program.
I think, based on the fact that there is a distinction. I don't know F#
Anyway gotta run but I'm sure someone can pick this up.
Arnau Abella
@monadplus
Blaž Marinović
@bmarinovic
The second example with a() is of type () -> int so I think it would be the same program
Arnau Abella
@monadplus
Remember that IO RT is broke when the IO (or the thunk in your example) is run.
Blaž Marinović
@bmarinovic

I read both of those already (I think, not 100% about first link) :D

Remember that IO RT is broke when the IO (or the thunk in your example) is run.

I remember, but I guess I still don't know the true meaning of it. Maybe there lies my confusion

but I think it's misleading to frame IO in terms of evaluation semantics

Anyone can expand on this?

Arnau Abella
@monadplus
From the second article: "Referential transparency: replacing an expression by its bound value doesn't alter the behaviour of your program."
Rob's example: With the code above if you had (a(), a()) and substituted val b = a(); (b, b) it would no longer be the same program
Fabio Labella
@SystemFw
@b4d3 actually I do mention using "thunks" or "functions" in one of those two reddit posts a bit
you indeed can get purity that way
I personally think it's way, way easier to mess it up
because you have linked it to your evaluation semantics
this is the same reason why I don't like effect systems btw
however, there are more reasons to not like a simple Function1 implementation like that one
for example, how do you do asynchrony/concurrency?
your model is basically () => A, which is synchronous
for asynchrony and therefore concurrency, you need
(A => Unit) => Unit
or, taking errors into account
(Either[Throwable, A] => Unit) => Unit)
which again, you can use directly, but then you get into callback hell
you will note that IO is capable of embedding both things
() => A, in its => A form, it's the argument to Sync[F].delay
(Either[Throwable, A] => Unit) => Unit) is the argument to Async[F].async