Where communities thrive


  • Join over 1.5M+ people
  • Join over 100K+ communities
  • Free without limits
  • Create your own community
People
Activity
  • Jan 31 2019 16:41
    etorreborre closed #162
  • Jan 31 2019 16:41
    etorreborre commented #162
  • Jan 31 2019 14:33
    vitold commented #162
  • Jan 30 2019 22:34
    benhutchison commented #162
  • Jan 30 2019 14:53
    vitold opened #162
  • Jan 26 2019 23:38
    robertbutacu starred atnos-org/eff
  • Jan 23 2019 09:30
    Navneet-gupta01 starred atnos-org/eff
  • Dec 27 2018 04:31
    jugalps starred atnos-org/eff
  • Dec 26 2018 16:07

    etorreborre on master

    Simpler implementation of appli… (compare)

  • Dec 26 2018 16:07
    etorreborre closed #161
  • Dec 26 2018 16:07
    etorreborre commented #161
  • Dec 24 2018 12:36
    kencyke starred atnos-org/eff
  • Dec 24 2018 05:18
    buzden synchronize #161
  • Dec 24 2018 02:36
    TakashiOshikawa starred atnos-org/eff
  • Dec 23 2018 13:59
    crossroad0201 starred atnos-org/eff
  • Dec 23 2018 08:17
    Nymphium starred atnos-org/eff
  • Dec 21 2018 15:05
    buzden synchronize #161
  • Dec 21 2018 14:28
    mflis starred atnos-org/eff
  • Dec 21 2018 11:58
    buzden synchronize #161
  • Dec 21 2018 06:00
    wangpengwen starred atnos-org/eff
Zachary Albia
@zalbia
I've been searching through conversations about eff and slick's DBIO effect in this gitter and it looks like someone has written a slick "DBIOEffect" that can be used in an eff effect stack. If there is one, can someone point me to github project for this somewhere?
Zachary Albia
@zalbia

So I ended up just doing:

  type _dbio[R] = DBIO |= R
  type _DBIO[R] = DBIO <= R

  final def fromDBIO[R: _dbio, A](a: DBIO[A]): Eff[R, A] =
    send[DBIO, R, A](a)

Then interpreting it by transforming the "stack" into effProgram.transform(dbioEffect.fromDBIO).runAsync.runAsync where a DbioEffect is:

class DBIOEffect(val db: BasicBackend#DatabaseDef) {
  val fromDBIO: DBIO ~> Task = new (DBIO ~> Task) {
    override def apply[A](fa: DBIO[A]): Task[A] =
      Task.defer(Task.fromFuture(db.run(fa)))
  }
}
Krisztian Lachata
@lachatak
Hi GUys. I believe you have been asked many times but is there a way to integrate/use eff together with fs2.Stream like use the stream with eff effect? Is it doable/recommened to use together? Have you got any working examples available? Thank you! Krisztian
Ben Hutchison
@benhutchison

@lachatak I think that is not yet a well explored/understood area. There are only few examples, and no supported "best practice" examples to build from yet.

Conceptually, it should be fine, FS2 was built effect agnostic. From https://functional-streams-for-scala.github.io/fs2/guide.html#building-streams:

FS2 does not care what effect type you use for your streams. You may use IO for effects or bring your own, just by implementing a few interfaces for your effect type (cats.effect.MonadError[?, Throwable], cats.effect.Sync, cats.effect.Async, and cats.effect.Effect if you wish to use various concurrent operations discussed later).

Practically though, you'll need a fairly solid understanding of Eff, Cats Effect and FS2 to integrate them smoothly, in my estimation.

Binzi Cao
@caobinzi
Hi Guys, I got a weird compliation error with the latest eff :
java.lang.AssertionError: assertion failed:
  AdaptTypeError - foundType is Erroneous: org.atnos.eff.Member[Object,org.atnos.eff.FxAppend[org.atnos.eff.Fx2[Object,Object],org.atnos.eff.Fx3[BankOp,cats.Eval,LogOp]]]{type Out = org.atnos.eff.FxAppend[org.atnos.eff.Fx1[<error>],org.atnos.eff.Fx3[BankOp,cats.Eval,LogOp]]}
build.sbt is like this :
scalaVersion := "2.12.6"

libraryDependencies += "org.atnos" % "eff_2.12" % "5.3.0"

scalacOptions += "-Ypartial-unification"
addCompilerPlugin("org.spire-math" %% "kind-projector" % "0.9.3")
any hints?
Binzi Cao
@caobinzi
Seems it is related to the function Interpret.transform function I’m using, will do some further check
Binzi Cao
@caobinzi
Please ignore ^^^, got it fixed by changing some existing code with the new transform function
Eric Torreborre
@etorreborre
No fix to do on the library side, great :-)
Binzi Cao
@caobinzi
@etorreborre Yeah, thanks very much. It did took me a while to figure out how transform works. I’m using natural transformation for all the effects.
Krisztian Lachata
@lachatak
@benhutchison sorry for the later response. Thx your response.
Marcin Flis
@mflis
Hi. Are there plans to release eff version containing cats-effects 1.0.0 soon? I wanted to use cats effect 1.0.0 along with with eff 5.3.0, but I had binary compatibility issues, so right now I've built my own eff package from master. I would prefer depending on package from maven central, rather than package from internal nexus.
Eric Torreborre
@etorreborre
Yes I would like to, I think doobie is holding off the release: tpolecat/doobie#769
dongli
@dongli2015

@etorreborre hi Eric, after updated dependency of eff from 5.0.0 to 5.3.0,

import org.atnos.eff.syntax.addon.cats.effect._

// Runner of the effect stack
effectStack
        .runTime(Clock.live)
        .runMonitorUnsafe(monitor.monitor)
        .runLogUnsafe(logger.log)
        .evalState[Context](ctx)
        .runReader[IdGenerator](IdGenerator.secure)
        .runEval
        .to[IO]

.to[IO] doesn't work any more. it's still in org.atnos.eff.syntax.addon.cats.effect. Probably the implicit IOOps doesn't work because the compiler doesn't see Eff[Fx1[IO], A], instead it's Eff[R, A] as it was before. I have no idea how to make it work. Could you help?

Ben Hutchison
@benhutchison

@dongli2015

  • The actual compiler error text you are seeing is valuable to help you, "doesn't work any more" isnt very specific description.

  • Its easier to diagnose problems with a simple stack. There's alot in your snippet that seems unrelated to the IO problem. Does it still happen with just one IO effect?

  • If you manually/explicitly invoke the implicit (thats allowed!), does it work. ie toIOOps(<eff expr>).to[IO]? if not whats the error?

  • I also suggest looking at the problems I was discussing in https://gitter.im/typelevel/cats-effect, we seem to need a implicit val contextShift = IO.contextShift(ExecutionContext.global) in scope in more recent versions of cats-effect, which your upgrade may have picked up

Eric Torreborre
@etorreborre
@dongli2015 sorry I’ve been totally missing from Gitter in the past month, being absorbed with my new job. Did you make any progress on your upgrade issue?
Roman Parykin
@donderom
Hi,
I'm trying to abstract over an effect but cannot make it work with Future
object Example {
  import org.atnos.eff._
  import org.atnos.eff.all._
  import org.atnos.eff.syntax.all._
  import scala.concurrent.Future
  import scala.concurrent.ExecutionContext.Implicits.global

  implicit val scheduler = ExecutorServices.schedulerFromGlobalExecutionContext

  trait Repo[M[_]] {
    def action: M[Unit]
  }

  def repoEff[R, M[_]](implicit repo: Repo[M], ev: M |= R): Repo[Eff[R, ?]] =
    new Repo[Eff[R, ?]] {
      def action: Eff[R, Unit] = Eff.send(repo.action)
    }

  trait Algebra[M[_]] {
    type _effect[R] = M |= R

    def program[R: _effect](implicit repo: Repo[M]): Eff[R, Unit] =
      for {
        _ ← repoEff[R, M].action
      } yield ()
  }

  implicit val optionRepo: Repo[Option] = new Repo[Option] { def action: Option[Unit] = Some(()) }
  implicit val optionFuture: Repo[Future] = new Repo[Future] { def action: Future[Unit] = Future(()) }

  object FutureAlgebra extends Algebra[Option]

  type Stack = Fx.fx1[Option]

  def run = FutureAlgebra.program.runOption.run
}
If I change it from Option to Future it does not work anymore
Dan Di Spaltro
@dispalt
are there any example projects using eff, I've been using it for years, but feel like I suck at organizing it
Binzi Cao
@caobinzi
@donderom I have been playing this as well , it seems eff does not support Future as a built-in effect, I guess it is because scala Future has side effects. You could use cats-effect IO for any Future needs.
For example:
IO.fromFuture(IO(Future{..}))
and if you want some IOs to be in parrallel, try parMapN , parSequence
Eric Torreborre
@etorreborre
@donderom I would also avoid Future which is side-effecting. There is a TimedFuture effect which encapsulates those side-effects: https://github.com/atnos-org/eff/blob/master/shared/src/main/scala/org/atnos/eff/FutureEffect.scala
Eric Torreborre
@etorreborre

@dispalt I have a rather strong opinion on the subject now. I would not use effects to organise a code base in the sense of having a DatabaseEffect, S3Effect, AuthenticationEffect and so on. I think it is better to use regular case classes, traits (for interfaces - no implementation) and a “wiring” library for this. My latest take on the subject is in Haskell: https://github.com/etorreborre/registry but I think the same idea can be applied to Scala (my previous idea on this: https://github.com/zalando/grafter)

Then the signatures of those components can be parametrized by a monad M which is specified at wiring time. Here you have different choices:

  1. IO for maximum interoperability between the components (because it means “anything can happen”)
  2. ZIO where you can have some guarantees about the kind of errors which can occur
  3. a monad transformer or some MTL constraints. This is unavoidable if you need to pass something like a RequestId across the calls of your whole application and then you need something like a MonadReader RequestId
  4. an Eff r stack which you can think of as an “extensible" monad transformer stack

In any case the monad you use needs to be more or less isomorphic to ReaderT r (IO (Either e)) but nothing more. If you add more “effects” to your monad Mit will be very difficult to use concurrency primitives or bracketing operations (at least in Haskell, in Scala the Eff library has some machinery to support this but at the expense of lots of internal complexity).

In my own work, the only large Scala application I created with Eff is using grafter for wiring and has effects like Task, FlowId, Error, Log and that’s all (Log actually should be a component not an effect).

I think that with this kind of set-up we get the best:

  • modularity
  • encapsulation
  • mocking
  • interoperability of components
  • ease of creation of a subset of the application
  • application lifecycle, with a clean assemble/start-up/run/shutdown separation
Dan Di Spaltro
@dispalt
@etorreborre I've read this a bunch of times, so thank you. I agree, I stopped doing the infrastructure style effects long ago, as it was too cumbersome. I definitely use eff as more of a MTL style.
I still kinda want to see some actual code in the wild doing something more complex than a simple toy app.
Ben Hutchison
@benhutchison

@etorreborre What do you mean by "Log actually should be a component not an effect", can you expand upon this?

Re the number of useful effects, I agree it seems to plateau; Error, Reader, Task are the usual suspects.

I use State effects myself, but I guess that depends if you're updating stateful memory-based system, or its a stateless system that sends all state to an external datastore. Also, I've externalized random RNG via a second orthogonal state effect at times and been happy with the outcome.

Logging via a Writer still seems to make conceptual sense to me.

Ive always used a monolithic IO effect to date, but Im sympathetic to the argument "if you believe in type-safety, shouldn't that apply to IO effect types too?"

When Ive tried the Cats built-in MTL features (after already being Eff fluent), it's seem about as cumbersome to do the same thing, but slightly less flexible
Binzi Cao
@caobinzi

I’ve been playing with tagless final and eff at the same time. I’m still investigating when I should just use tagless final or just eff. I also found eff is much more powerful than tagless when dealing with different effects, because I can use eff to handle multiple effects and I can even wrap an effect with another effect automatically. Some sample code I have tried to use both tagless and eff is as below:

def program[
      F1[_]: FlatMap, //Tagless effect 1
      F2[_]: FlatMap, //Tagless effect 2
      F3[_]: FlatMap, //Tagless effect 3
      R:     MemberIn[LogOp, ?]: MemberIn[Option, ?]: MemberIn[F1, ?]: MemberIn[F2, ?]: MemberIn[F3, ?]
  ](
      gdpr:    GdprOp[F1],
      user:    UserOp[F2],
      console: ConsoleOp[F3]
  ): Eff[R, Unit]

But I’m still not sure if I should just choose one instead of mixing eff and tagless final. any thoughts?

Ben Hutchison
@benhutchison

I dont use tagless final myself but from a casual glance it looks like double abstraction/indirection to me.

My heuristic is to use the simplest solution that works, only take on extra complexity when you know you need it. I did FP without monad stacks for several years, only moved to MTL/Eff when I noticed the complexity ended up higher without monads in a large codebase, eg symptoms: implicit context passing, nested for expressions.

Binzi Cao
@caobinzi
@benhutchison Agree! I found we have so many good libraries in FP now, but it seems we need some FP design rules or how to orginize a real project with FP properly.
Dan Di Spaltro
@dispalt
yeah I like that idea
someone did a good pet store in fp example
I kinda like how @etorreborre thinks about this stuff so I'd love to see a bigger section of a full program to reverse some knowledge from it =)
Eric Torreborre
@etorreborre

@benhutchison you can leave Log as an effect but you don’t have to. Advantages: the Log effect can manage its own environment and be similar to a ReaderT RequestId m ()to log requests with their id. Disadvantage: you cannot wire some logging behaviour for one part of your app and another behaviour for another part (not sure if that’s really needed anyway). Note that if you have Log as a component that does not make your whole stack infected with IO. You can defined the Log component as

data Logger m = Logger {
  info :: Text -> m ()
, error :: Text -> m ()
}

And have your app instantiated in IO while your test code is instantiated with WriterT IO and you use the Writer instance to collect the logs.

Artur Gajowy
@ArturGajowy

Hi! First of all, thank you for this project - I'm very excited to start using it!

I'm considering migrating from cats-mtl transformers to eff, because abstracting over the 5-level stack I have is really hard with mtl typeclasses. My question would be: how does eff compare in terms of performance to 1. mtl transformers, 2. a fused mtl stack used via typeclasses (assuming for a while it's feasible to remain sane after seeing the resulting signatures)?

Artur Gajowy
@ArturGajowy
Also, how hard would it be to provide an effect equivalent to the below StreamT monad transformer?
final case class StreamT[F[_], A](value: F[Stream[A]]) {
  def ap[B](f: F[A => B])(implicit F: Monad[F]): StreamT[F, B] =
    StreamT(F.flatMap(f)(ff => F.map(value)((stream: Stream[A]) => stream.map(ff))))

  def map[B](f: A => B)(implicit F: Functor[F]): StreamT[F, B] =
    StreamT(F.map(value)(_.map(f)))

  def flatMap[B](f: A => StreamT[F, B])(implicit F: Monad[F]): StreamT[F, B] =
    flatMapF(a => f(a).value)

  def flatMapF[B](f: A => F[Stream[B]])(implicit F: Monad[F]): StreamT[F, B] =
    StreamT(Monad[F].flatMap(value)(astream => astream.flatTraverse(a => f(a))))
}
Eric Torreborre
@etorreborre
Hi @ArturGajowy. I’ve never done any real benchmarks but Eff is not really optimised so I don’t think it will compared favourably in tight loops especially in case 2.
I don’t know the answer to your second question. I think that we have to consider that we have a Streaming effect which can be interleaved with other effects. In that case a “Streaming” effect could be supported by a simple Yield a primitive to return the next element in the stream. However this is likely to be super slow. Most streaming libraries support the idea of “chunking” the data in memory to operate on whole “blocks” at the time. So I would probably turn to one of those libraries
Artur Gajowy
@ArturGajowy
The stream is used for handling non-determinism lazily, so perf is not that big of an issue here
Thx for the answer! I guess I'll give it a try anyway and then try to do some benchmarks
kusamakura
@kusamakura
Hello! I've been enjoying Eff lately, but like others in this channel, I'm running into some organizational concerns. I have an interface that is parameterized on a Monad, tagless-final style. Some methods return Option[A] or ThrowableEither[A], and some eventually rely on a Clock effect. So when I use Eff[R, ?] as the service's Monad, I then have to include the superset stack of effects, which pollutes the methods when calling them. I was thinking that I can have an all-encompassing IO effect as the base stack, and then each method would have its own if necessary... What's the ideal way to go about handling this? X)
Eric Torreborre
@etorreborre
Can you please illustrate the “pollutes the methods” part? And “each method would have its own if necessary?
Ben Hutchison
@benhutchison

@kusamakura I think having to acknowledge all effects used in that call-tree, in the type signature, is a feature not a bug ;)

Note you can extend the stack in particular parts of your program, see eg http://atnos-org.github.io/eff/org.atnos.site.Cookbook.html

kusamakura
@kusamakura

@etorreborre Sorry for the late reply and for the unclear description, but @benhutchison read my intent correctly. It's about choosing between 1) putting all effects of all methods in the interface itself, or 2) putting only necessary effects in the methods themselves. I suppose what I wanted to say was that for choice 1 (which I'm currently using), I have to deal with effects that aren't even in use in some methods. To put it concretely:

import org.atnos.eff._
import org.atnos.eff.all._
import org.atnos.eff.syntax.all._

trait GreetingsRepo[M[_]] {
  def get(id: Long): M[String]
  def create(id: Long, greeting: String): M[Unit]
}

class EffGreetingsRepo[R: _Eval: _Option: _ThrowableEither] extends GreetingsRepo[Eff[R, ?]] {
  private[this] val map = collection.mutable.Map.empty[Long, String]

  def get(id: Long): Eff[R, String] =
    delay(map.get(id)).flatMap(fromOption(_))

  def create(id: Long, greeting: String): Eff[R, Unit] =
    map.get(id) match {
      case Some(_) => left[R, Throwable, Unit](new Throwable("already exists"))
      case _ => delay(map.update(id, greeting)).flatMap(right(_))
    }
}

val repo = new EffGreetingsRepo[Fx.fx3[Eval, Option, ThrowableEither]]

// Option[Either[Throwable, String]], ideally just Option[String]
// I realize that I can also take away the Option effect completely,
// in favor of using `either.optionEither` instead of `option.fromOption`
val doGet = repo.get(1L).runEither[Throwable].runOption.runEval.run

I think I just need to understand more of Eff, but I guess this isn't so bad since dealing with this only happens at the end of the world anyway. In any case, thank you for your continued effort in this project/space. :)

Eric Torreborre
@etorreborre
I think that choice n.1 is generally not that bad but in you example I would probably put _Option in the return type directly, like get(id: Long): Eff[R, Option[String]]
kusamakura
@kusamakura
Thanks for the feedback, @etorreborre. I've settled on something like that as well. I suppose I was too excited to move all effects from the return type into the effects stack :p
kaichao
@kaichaosun
Is the Eff[ConnectionIO] still maintain the transaction provided by doobie?
Eric Torreborre
@etorreborre
@dashengSun Eff[R, A] where ConnectionIO |= R is a program having some ConnectionIO effects which means having a ConnectionIO “program” which itself is a set of instructions requiring a database connection to be executed. This is why when you run that effect with runConnectionIO you need to pass a Transactor which contains that connection to the database (actually a connection from a pool of connections)