Sequence of monadic functions from A to B: A => Eff[B]
Sequence of monadic functions from A to B: A => Eff[B]
Internally it is represented as a Vector of functions:
A => Eff[R, X1]; X1 => Eff[R, X2]; X2 => Eff[R, X3]; ...; X3 => Eff[R, B]
An alternate unit value can also be set on this function in case the argument A is not available. This value can be set by an effect to do some cleanup if it doesn't even get the chance to add its own effect. See SafeEffect.bracket
This trait provides a way to rewrite applicative effects when there is an operation allowing the batching of some effects based on the Batchable typeclass
This cache is used to memoize values for the Memoized effect
The Choose effect models non-determinism So we can get results, either:
The Choose effect models non-determinism So we can get results, either:
When running this effect we can "collect" the results with any F which has an Alternative instance.
For example if F is List then:
If F is Option then:
Collection of effects of a given type from a Unions objects
Effects of type R, returning a value of type A
Effects of type R, returning a value of type A
It is implemented as a "Free-er" monad with extensible effects:
Arrs
typeThe monad implementation for this type is really simple:
point
is Purebind
simply appends the binding function to the Arrs
continuationImportant:
The list of continuations is NOT implemented as a type sequence but simply as a Vector[Any => Eff[R, Any]]
This means that various .asInstanceOf
are present in the implementation and could lead
to burns and severe harm. Use with caution!
Similarly the list of effects in the applicative case is untyped and interpreters for those effects are supposed to create a list of values to feed the mapping function. If an interpreter doesn't create a list of values of the right size and with the right types, there will be a runtime exception.
The Pure, Impure and ImpureAp cases also incorporate a "last" action returning no value but just used for side-effects (shutting down an execution context for example). This action is meant to be executed at the end of all computations, regardless of the number of flatMaps added on the Eff value.
Since this last action will be executed, its value never collected so if it throws an exception it is possible to print it by defining the eff.debuglast system property (-Deff.debuglast=true)
http://okmij.org/ftp/Haskell/extensible/more.pdf
one effect, basically a type constructor
Effect for computation which can fail
Effect for computation which can fail and return a Throwable, or just stop with a failure
Effect for computation which can fail and return a Throwable, or just stop with a failure
This effect is a mix of Eval and Either in the sense that every computation passed to this effect (with the ok method) is considered "impure" or "faulty" by default.
The type F is used to represent the failure type.
Effect for delayed computations
Effect for delayed computations
uses cats.Eval as a supporting data structure
Base type for a tree of effect types
Append a tree of effects to another one
Impure is an effect (encoded as one possibility among other effects, a Union) and a continuation providing the next Eff value.
Impure is an effect (encoded as one possibility among other effects, a Union) and a continuation providing the next Eff value.
This essentially models a flatMap operation with the current effect and the monadic function to apply to a value once the effect is interpreted
One effect can always be executed last, just for side-effects
ImpureAp is a list of independent effects and a pure function creating a value with all the resulting values once all effects have been interpreted.
ImpureAp is a list of independent effects and a pure function creating a value with all the resulting values once all effects have been interpreted.
This essentially models a sequence + map operation but it is important to understand that the list of Union objects can represent different effects and be like: Vector[Option[Int], Future[String], Option[Int]].
Interpreting such an Eff value for a given effect (say Option) consists in:
VERY IMPORTANT:
Support methods to create interpreters (or "effect handlers") for a given effect M and a value Eff[R, A] when M is a member of R.
Support methods to create interpreters (or "effect handlers") for a given effect M and a value Eff[R, A] when M is a member of R.
Those methods guarantee a stack-safe behaviour when running on a large list of effects (in list.traverse(f) for example).
There are different types of supported interpreters:
This interpreter is used to handle effects which either return a value X from M[X] or stops with Eff[R, B] See an example of such an interpreter in Eval where we just evaluate a computation X for each Eval[X].
2. "interpretState" + StateRecurse
This interpreter is used to handle effects which either return a value X from M[X] or stops with Eff[R, B]
3. "interpretLoop" + Loop
The most generic kind of interpreter where we can even recurse in the case of Pure(a) (See ListEffect for such a use)
4. "intercept / interceptState / interceptLoop" methods are similar but they transform an effect to other effects in the same stack without removing it from the stack
5. "transform" to swap an effect T of a stack to another effect, using a Natural Transformation
6. "translate" to interpret one effect of a stack into other effects of the same stack using a Natural Transformation this is a specialized version of interpret + Recurse
7. "interpretUnsafe + SideEffect" when you have a side effecting function M[X] => X
Typeclass proving that it is possible to send a tree of effects R into another tree of effects U
Typeclass proving that it is possible to send a tree of effects R into another tree of effects U
for example
send[Option1, Fx.fx3[Option1, Option2, Option3], Int](Option1(1)). into[Fx.fx5[Option1, Option2, Option3, Option4, Option5]]
should work because all the effects of the first stack are present in the second
Note: some implicit definitions are probably missing in some cases
Encapsulation of one optional last action to execute at the end of the program
support trait for folding values while possibly keeping some internal state
Effect for computations possibly returning several values
Generalisation of Recurse and StateRecurse
Generalisation of Recurse and StateRecurse
The loop defines some state with an initial value which is maintained at each step of the interpretation.
A is the type of Eff values to interpret, and B is the result of the interpretation (generally an other Eff value)
C is the type of result for "last" actions.
- the interpretation of a Pure value either returns the final result or possibly one more Eff value to interpret
- onEffect interprets one effect and possibly uses the continuation to produce the next value to interpret. If no X can be used to run the continuation we might just output one final B value
Memoization effect
Memoization effect
Memoize a computation for a given key
This effect can be interpreted with a cache implemented with many different libraries. See Cache.scala for 2 default implementations:
You can implement your own version using ScalaCache for example
The "empty" tree of effects
Effect for optional computations
This class can be used as a F in runChoose to generate random alternatives
Effect for computations depending on an environment.
Effect for computations depending on an environment.
The inside datatype for this effect is cats.data.Reader
Helper trait for computations which might produce several M[X] in a stack of effects.
Helper trait for computations which might produce several M[X] in a stack of effects.
Either we can produce an X to pass to a continuation or we're done
For the applicative case we expect to be able to traverse a list of effects and return an effect of a list of results OR completely consume the effect and return a pure list of values
The Safe type is a mix of a ThrowableEither / Eval effect and a writer effect to collect finalizer failures
The design of the Scheduler is taken from: https://github.com/functional-streams-for-scala/fs2/blob/series/1.0/core/jvm/src/main/scala/fs2/Scheduler.scala
type class for effects which can be cached in a SequenceCache
Effect for passing state along computations
Effect for passing state along computations
Internally backed up by cats.data.State
Generalisation of Recurse
trait for translating one effect into other ones in the same stack
Union represents one effect T[_] embedded in a tree of possible effects R
Union represents one effect T[_] embedded in a tree of possible effects R
The effect tree is represented by four possible cases:
The union type has three concrete constructors:
transform a Union for a given stack into a Union for another stack
A non-empty list of Unions.
A non-empty list of Unions.
It is only partially typed, we just keep track of the type of the first object
Effect for computation which can fail but will accumulate errors
Effect for computation which can fail but will accumulate errors
The runValidate interpreter just collects the messages and returns them at the end
Effect for logging values alongside computations
Effect for logging values alongside computations
Compared to traditional Writer monad which accumulates values by default this effect can be interpreted in different ways:
Simple instantiation of the ErrorEffect trait with String as a Failure type
This effect is used in the implementation of the Async effect