[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [MirageOS-devel] Error handling in Mirage - request for comments!



> System 3 provides (I think) no easy way to match on the type of error.

You can. An Error.t is constructed by using Sexplib. Thus, you can deserialize them to whatever specific error you want to consider. Here's an example:

open Core.Std;;

type myerr = [`Zero | `Neg of int] with sexp;;

(* Get back to myerr if possible. *)
let myerr_of_error (e:Error.t) : myerr option =
 match Error.sexp_of_t e with
 | Sexp.List (_::x::[]) -> Some (myerr_of_sexp x)
 | _ -> None
;;

let f x : int Or_error.t =
 if x = 0 then error "zero not allowed" `Zero sexp_of_errorÂ
 else if x < 0 then error "negative not allowed" (`Neg x) sexp_of_error
 else Ok x
;;

let g x = match f x with
| Ok x -> x*x
| Error e -> match myerr_of_error e with
 | Some `Zero -> 0
 | Some (`Neg x) -> x*x
 | None -> 0 (* or parse e as another error type *)
;;

In the last None clause above, you could try to parse e as another error type, continuing to consider as many error types as you want. The nice thing about this is you only have one error type, Error.t, so your APIs remain uncluttered. But you can deserialize to more strongly typed error types when you want to.

The bad thing is the compiler can't tell you what are all the errors you have to consider, but this isn't achieved my most error handling strategies. Furthermore, this is all about errors, so I'm not sure exhaustiveness is so important.


> Sometimes it's useful to organise errors into a hierarchy ... I don't see any way to do this in OCaml.

You can get this with polymorphic variants, e.g

type tcp_connection_refused = [`TCP_connection_refused]
type tcp_error = [tcp_connection_refused | `Another_err]



On Tue, Feb 3, 2015 at 12:26 PM, Sebastien Mondet <sebastien.mondet@xxxxxxxxx> wrote:

Yes if we just all agree on this type: http://erratique.ch/software/fut/doc/Fut.html#TYPEresult
then we are all compatible without actual library dependencies, thanks to structural typing

I've been abusing this for the past few years, it's great:
http://seb.mondet.org/software/pvem/index.html
http://seb.mondet.org/software/pvem_lwt_unix/index.html
http://seb.mondet.org/talks/compose2015/#/25
http://seb.mondet.org/talks/compose2015/#/26







On Tue, Feb 3, 2015 at 12:10 PM, Daniel BÃnzli <daniel.buenzli@xxxxxxxxxxxx> wrote:
Le mardi, 3 fÃvrier 2015 Ã 16:55, Christophe Troestler a Ãcrit :
> Please lay down a concrete interface showing of what you mean. I
> think we all agree on the goal of writing robust software, we need to
> move the discussion to concrete proposals.

Sorry don't have the time to work on this; these things come out of writing code. But as a start I don't see what's the problem with the basic result monad everybody knows (e.g. see here [1,2]) along with a few with_resource combinators based on some kind of `finally` [3] and stick to polymorphic variant errors â along, of course, with Format pretty printers for these something that is often annoyingly absent in APIs. And I would completely forget about using lwt's failed state (i.e. only to trap unexpected exceptions at the highest level).

Best,

Daniel

[1]
This deals only with string errors so it should be generalized to [2], but a few of the error handling
combinators may be interesting.

https://github.com/samoht/assemblage/blob/master/lib/assemblage.mli#L708-L744

For example `reword_error` a quick combinator that allows to transform a lower-level error to a higher level one, i.e. give more context higher up when you have the info about what you are doing. Since we are using strings here it's also easy to stack the errors if you wish so (~replace:false argument) from the lowest-level of what went wrong (e.g. the actual utility invocation error) to what you were trying to do (e.g. determine the number of processors in the system) which makes error diagnosis much easier (context + no error info is lost). Not that it wouldn't be impossible with lists of polyvars, but one has to see how it comes out in practice. A few examples:

https://github.com/samoht/assemblage/blob/master/lib/as_conf.ml#L420-L428
https://github.com/samoht/assemblage/blob/master/lib/as_conf.ml#L543-L548

[2]
This is the classical generalized result type for dealing with errors.
http://erratique.ch/software/fut/doc/Fut.html#TYPEresult
http://erratique.ch/software/fut/doc/Fut.html#VAL(&>>=) (http://erratique.ch/software/fut/doc/Fut.html#VAL(&%3E%3E=))
http://erratique.ch/software/fut/doc/Futu.html#VALread

[3]
http://erratique.ch/software/fut/doc/Fut.html#VALfinally
This could also be modified or another version provided to propagate possible errors in the finally handler in the concurrency monad itself.


_______________________________________________
MirageOS-devel mailing list
MirageOS-devel@xxxxxxxxxxxxxxxxxxxx
http://lists.xenproject.org/cgi-bin/mailman/listinfo/mirageos-devel


_______________________________________________
MirageOS-devel mailing list
MirageOS-devel@xxxxxxxxxxxxxxxxxxxx
http://lists.xenproject.org/cgi-bin/mailman/listinfo/mirageos-devel


_______________________________________________
MirageOS-devel mailing list
MirageOS-devel@xxxxxxxxxxxxxxxxxxxx
http://lists.xenproject.org/cgi-bin/mailman/listinfo/mirageos-devel

 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.