You baked in error handling into your IO type. This is ligitmate, but it would be better if we could compose effects. With map effect composition is easy. But with and_then it becomes hard. Why? Because now and_then can create an effect depending on a previous value. Think about an Option type with two cases Some(x)/None where None embodies a computation without a result. With map you can have a Some([1,2,3]) or a None. But with and_then you can have Some[0,2,3] and for the first element and_then produces a None, because you use it in a devision, for instance. What now? What is the combined semantics of this effect? The result could be Some[float, float] or it could be None. Picking one semantics isn't hard but guaranteeing that all possible effects can be composed is.
I think there are pros and cons to both solutions. The reason I chose to bake error handling into our IO type here is because the python type system doesn't support higher-kinded types, and in general, in order to compose effects "horizontally" as you suggest with type safety (e.g with monad transformers) you need higher-kinded types. For that reason I think this "vertical" effect composition is more well suited for Python.
I'm not sure I understand your question completely, but I take it to be: How does error handling work when you compose Effect and list (i.e Effect[List[int]]). My library doesn't provide any special helper methods for that case (I'm not sure why you would need it), but if you swap the order of composition to List[Effect[int]], you can use many different provided helper functions to produce new effects that aggregate on such a list, e.g sequence_async(List[Effect[int]]) -> Effect[List[int]] (semantically equivalent to sequence in haskell). In that case if one effect in the list fails, the resulting effect also fails (again, same as in haskell). Apologies if I misunderstood your comment :)
For further actions, you may consider blocking this person and/or reporting abuse
We're a place where coders share, stay up-to-date and grow their careers.
You baked in error handling into your
IO
type. This is ligitmate, but it would be better if we could compose effects. Withmap
effect composition is easy. But withand_then
it becomes hard. Why? Because nowand_then
can create an effect depending on a previous value. Think about anOption
type with two casesSome(x)
/None
whereNone
embodies a computation without a result. Withmap
you can have aSome([1,2,3])
or aNone
. But withand_then
you can haveSome[0,2,3]
and for the first elementand_then
produces aNone
, because you use it in a devision, for instance. What now? What is the combined semantics of this effect? The result could beSome[float, float]
or it could beNone
. Picking one semantics isn't hard but guaranteeing that all possible effects can be composed is.I think there are pros and cons to both solutions. The reason I chose to bake error handling into our IO type here is because the python type system doesn't support higher-kinded types, and in general, in order to compose effects "horizontally" as you suggest with type safety (e.g with monad transformers) you need higher-kinded types. For that reason I think this "vertical" effect composition is more well suited for Python.
I'm not sure I understand your question completely, but I take it to be: How does error handling work when you compose
Effect
andlist
(i.eEffect[List[int]]
). My library doesn't provide any special helper methods for that case (I'm not sure why you would need it), but if you swap the order of composition toList[Effect[int]]
, you can use many different provided helper functions to produce new effects that aggregate on such a list, e.gsequence_async(List[Effect[int]]) -> Effect[List[int]]
(semantically equivalent tosequence
in haskell). In that case if one effect in the list fails, the resulting effect also fails (again, same as in haskell). Apologies if I misunderstood your comment :)