I am writing a function that stores a key value pair asynchronously. The key is a string but the value is supplied as an async stream so that it can be streamed to the key-value store without loading the whole value into memory. I am making use of lwt
for async and the result
type to represent success/failure.
What I am struggling with is how to combine the error type of the input value stream with the error type that represents an error writing to the key-value store. I think this problem can be represented without the async twist, but I wanted to leave it in to show that the value cannot be resolved before calling this function.
Currently, what I have looks something like this:
val store:
t -> (* client *)
string -> (* key *)
Bigstringaf.t Lwt_stream.t -> (* value to store. contents are streamed in asynchronously *)
(unit, 'error) Lwt_result.t -> (* promise that indicates whether contents stream succeeded or failed *)
(unit, [ `Contents_error of 'error | ClientError.t ]) Lwt_result.t (* ClientError.t is a polymorphic variant type *)
I was hoping to able to constrain the 'error
type parameter to be a polymorphic variant so that I could do this:
val store:
t -> (* client *)
string -> (* key *)
Bigstringaf.t Lwt_stream.t -> (* value to store. contents are streamed in asynchronously *)
(unit, 'error) Lwt_result.t -> (* promise that indicates whether contents stream succeeded or failed *)
(unit, [> 'error | ClientError.t ]) Lwt_result.t (* NOTE the `Contents_error variant is no longer needed *)
Is there a way to add the polymorphic variant constraint? If not, is there a better approach to combining variants?
If possible, I would like to avoid the “big ball of mud” error approach (often found in Rust) where every error that can occur in the program/library is added to one giant error variant. I don’t like this approach because it makes it hard to know which errors actually need to be handled after calling a function, which is, IMHO, the biggest advantage of the result
type to begin with! But I am open to being convinced otherwise.