Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Result.WithContext #26

Open
cmorley191 opened this issue May 16, 2019 · 2 comments
Open

Result.WithContext #26

cmorley191 opened this issue May 16, 2019 · 2 comments

Comments

@cmorley191
Copy link

This is somewhat of a followup to #25

While I think mapError is probably a good method to simply have, I think it may just be a first step towards more descriptive errors. Another feature may be to add some sort of framework for simply adding details to an error message, without changing it to a new type.

  • Add some sort of generic type, like ResultError<'a>
    • Holds the original 'a error, as well as a list (or dictionary?) of error details
    • Supports an withDetails(details:string) or withContext(details:string) to add further context to the error being thrown (add an element to the detail collection)
  • Add a Result.WithContext method to call "withContext" on the inner ResultError<...>:
let WithContext context (result:Result<'ok, 'err>) where 'err :> ResultError<'suberr> =
  result.mapError (fun err -> err.withContext(context))
  • Add a Result.Contextual method to wrap a non-contextual error type into a contextual one:
let Contextual context (result:Result<'ok, 'err>) : Result<'ok, ResultError<'err'>> =
  result.mapError (fun err -> (ResultError err).withContext(context))
  • Finally, these details can be translated into other error contexts. For example, Result.Expect should take the details and add them to the ResultExpectedException's Exception Message or Data field, so the error's context is visible in the resulting exception.
@ntwilson
Copy link
Owner

Yeah, this is a really interesting idea. I want to think about it a little more. I don't want it to get too specific for something that is only slightly more work using the abstract approach:

let x = Seq.head' xs |> Result.mapError List.singleton
...
let y = x |> Result.mapError (fun e -> "while doing xyz" :: e)

the thing is, that would only work for Results where the error is a string. Seq.head' for example, returns a Result<'a, SeqIsEmpty>, which is really nice for inference, because you can see by the type signature what could go wrong. So maybe that's where this context object could be really handy. If we could keep the signature looking something like Result<'a, ErrorDetails<SeqIsEmpty>>, but have it include some list of contextual info in strings or something, that could be really cool.
But is that too specific and opinionated for this library? Should that exist here or somewhere else?

@ntwilson
Copy link
Owner

see this pull request for a strawman implementation and further discussion on this.
Notably, I wonder if this should be done in v. 3.0 along with putting the C# Result type into a ResultDotNet.CSharp namespace instead of just the root ResultDotNet namespace.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants