Closed struktured closed 9 years ago
If you will copy Result
you will get different one, that is incompatible with the core's one. That means, that a user who actually uses both future and core library will be unable to apply core functions on this Result.t
. This will even introduce lots of problems, as Future's result constructors will hide Core's or vice verse.
But there are good news, by the way, very soon Result.t
will become a part of standard library.
My overall response is: Why shouldn't we depend on Core_kernel? More specific responses below:
The monad signatures can be directly copied without trepidation from core_kernel into future. ... Result is also fairly trivial and can be copied directly from core_kernel.
Why copy code? That's usually a bad thing.
Alternatively you could use an existing library if the signatures line up enough like rresult.
Core is also an existing library. I'm not sure why rresult, a library released only recently, should be preferred over an established industrial strength library.
Regarding cfstream, which depends on core_kernel, you could use something such as gen for non core/async related implementations, and still cfstream otherwise.
So now we use gen
, yet another library, instead of the completely well established Stream that is part of the standard library. Why?
I don't know how important these Or_error.List functions are really
If you use Or_error, which I do, then they are very useful.
instead of forcefully injecting Error.t with its sexp semantics
What's wrong with sexplib? It is widely used and extremely stable. Maybe you don't want to use camlp4 extensions, which I do understand. However, you can use Error.t perfectly well without camlp4.
Consider the amount of work and levels of indirection you are proposing. Is there really a good justification for it?
Ok, so I think meant to copy the signatures, not the implementations, which should help resolve the Result.t
constructor issues mentioned by @ivg? I agree that copying implementations is not desirable.
I personally don't have a problem with core_kernel but I'm concerned that it alienates some of the community as too heavy of a dependency. I suppose a lighter core_kernel is on its way so perhaps that will mitigate the issue.
Sexplib isn't bad but I wouldn't go as far to force it upon someone for an error handling strategy (I prefer polymorphic variants myself, for instance).
I personally don't have a problem with core_kernel but I'm concerned that it alienates some of the community as too heavy of a dependency.
Let's prioritize current users over hypothetical ones. If we're happy with Core_kernel, then no reason to avoid it really. I've heard all the arguments against Core, and my feeling on each point is either: I don't agree, or yes it is a problem which the Core team is actively working on, or yes it is a problem that no one has a good solution for.
Sexplib isn't bad but I wouldn't go as far to force it upon someone for an error handling strategy (I prefer polymorphic variants myself, for instance).
I like polymorphic variants for error handling too, but I did experiments with it and came to the conclusion that imposing that on users would also be bad. I'm still double minded about it, and think it could be the right choice in some cases. But not in 100% of the cases, so another simpler choice is also important, and I think Or_error hits the sweet spot. We've been discussing this for a few years on the Biocaml mailing list and internally. Error handling is one of those problems that I feel is really hard and no one has a good solution for.
I wasn't suggesting forcing my own error handling strategy- I'm proposing to make Error.t
functorized so an error handling strategy is imposed only after committing to a particular concurrent implementation. Also, do you have a link to that forum thread?
I wasn't suggesting forcing my own error handling strategy
Right, I did understand that you're asking to abstract over it, and let the user pick different styles. I should clarify that I'm not inherently opposed to any of your suggestions. It would be nice to give users the choice of different error handling strategies, and over all the different modules Core provides. Why not let people pick Batteries instead; that would be nice. Well, it takes work to provide, maintain, and use such abstractions, so there should be a clear benefit, which I don't see in the current case.
do you have a link to that forum thread?
Our summary is here, but note the "TO DO" at the very end. The issue of what information to put in the Error is still open after 3 years! This thread discussed exceptions vs Result, and this one discussed the use of polymorphic variants as the type of error information. Then there was a 3rd thread, but I just lost energy to read it all, and tell you what it was about. Jane Street wrote a blog about Or_error. Finally, there is a lengthy discussion on MirageOS-devel, which discusses this nice summary.
meant to copy the signatures, not the implementations, which should help resolve the Result.t constructor issues mentioned by @ivg?
I agree. I think you could make types compatible.
Happy to keep discussing... but closing the issue as there isn't a pending action item here.
Cool thanks for the discussion! On Sep 29, 2015 3:21 PM, "Ashish Agarwal" notifications@github.com wrote:
Closed #13 https://github.com/agarwal/future/issues/13.
— Reply to this email directly or view it on GitHub https://github.com/agarwal/future/issues/13#event-422283863.
I know you intend on requiring core_kernel, but I feel like it wouldn't be terribly hard to remove core_kernel itself as strong dependency, and instead be an optional one just like lwt or async.
As far as I can tell, most of the dependency on core_kernel comes from the monad signatures
Monad.S*
,Result
, andOr_error
. The monad signatures can be directly copied without trepidation from core_kernel into future.Result
is also fairly trivial and can be copied directly from core_kernel. Alternatively you could use an existing library if the signatures line up enough like rresult.Now, let's assume
Or_error
is truly worth being exposed in the future api (is it? I don't know how important theseOr_error.List
functions are really).Then, instead of forcefully injecting
Error.t
with its sexp semantics and otherwise, we define a very abstractError.S
signature that core_kernel'sError.t
adheres to, and provisional ones can be made for lwt which would not depend on core. Since'a Or_error.t = ('a, Error.t) Result.t
, this type doesn't have to syntactically change, which is nice.Regarding cfstream, which depends on core_kernel, you could use something such as gen for non core/async related implementations, and still cfstream otherwise. This is easy because both libraries are essentially swap in replacements of each other for most functions.
I started doing some of the above changes in a fork but it's very experimental and doesn't compile at the moment. While I know this wasn't your goal with future, I wanted you to consider it once more before completely punting on the idea. I am willing to do most of the work involved if that's your biggest concern about it.