Created
December 8, 2020 19:42
-
-
Save keleshev/c8d6d8adac646839fdc6664d44cb91c6 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(* https://keleshev.com/composable-error-handling-in-ocaml *) | |
open Printf | |
let (>>=) = Result.bind | |
let (let*) = Result.bind | |
module Exceptions_example (X: sig | |
type tree | |
module Parser : sig | |
exception SyntaxError of int | |
exception GrammarError of {line: int; message: string} | |
(** Can raise [Parser.SyntaxError] or [Parser.GrammarError] *) | |
val parse : string -> tree | |
end | |
module Validation : sig | |
exception LengthError of int | |
exception HeightError of int | |
(** Can raise [Validation.LengthError] or [Validation.HeightError] *) | |
val perform : tree -> tree | |
end | |
module Display : sig | |
exception Error of string | |
(** Can raise [Display.Error] *) | |
val render : tree -> string | |
end | |
end) = struct | |
open X | |
let main source = | |
let tree = Parser.parse source in | |
let tree = Validation.perform tree in | |
Display.render tree | |
open Printf | |
let handle_errors source = | |
try | |
printf "%s" (main source) | |
with | |
| Parser.SyntaxError line -> | |
eprintf "Syntax error at line %d" line | |
| Parser.(GrammarError {line; message}) -> | |
eprintf "Grammar error at line %d: %s" line message | |
| Validation.LengthError length -> | |
eprintf "Validation error: length %d is out of bounds" length | |
| Validation.HeightError height -> | |
eprintf "Validation error: height %d is out of bounds" height | |
| Display.Error message -> | |
eprintf "Display error: %s" message | |
end | |
module Result_with_strings_example (X: sig | |
type tree | |
module Parser : sig | |
val parse : string -> (tree, string) result | |
end | |
module Validation : sig | |
val perform : tree -> (tree, string) result | |
end | |
module Display : sig | |
val render : tree -> (string, string) result | |
end | |
end) = struct | |
open X | |
let main source = | |
match Parser.parse source with | |
| Error message -> | |
eprintf "Parser error: %s" message | |
| Ok tree -> | |
match Validation.perform tree with | |
| Error message -> | |
eprintf "Validation error: %s" message | |
| Ok tree -> | |
match Display.render tree with | |
| Error message -> | |
eprintf "Display error: %s" message | |
| Ok output -> | |
printf "%s" output | |
(* * *) | |
let main source = | |
Result.bind (Parser.parse source) (fun tree -> | |
Result.bind (Validation.perform tree) (fun tree -> | |
Display.render tree)) | |
let main2 source = | |
Parser.parse source >>= fun tree -> | |
Validation.perform tree >>= fun tree -> | |
Display.render tree | |
let main3 source = | |
let* tree = Parser.parse source in | |
let* tree = Validation.perform tree in | |
Display.render tree | |
(* * *) | |
let handle_errors source = | |
match main source with | |
| Error message -> eprintf "Error: %s" message | |
| Ok output -> printf "%s" output | |
end | |
module Result_with_variant_example (X: sig | |
type tree | |
module Parser : sig | |
type error = | |
| SyntaxError of int | |
| GrammarError of {line: int; message: string} | |
val parse : string -> (tree, error) result | |
end | |
module Validation : sig | |
type error = | |
| LengthError of int | |
| HeightError of int | |
val perform : tree -> (tree, error) result | |
end | |
module Display : sig | |
val render : tree -> (string, string) result | |
end | |
end) = struct | |
open X | |
let main source = | |
match Parser.parse source with | |
| Error Parser.(SyntaxError line) -> | |
eprintf "Syntax error at line %d" line | |
| Error Parser.(GrammarError {line; message}) -> | |
eprintf "Grammar error at line %d: %s" line message | |
| Ok tree -> | |
match Validation.perform tree with | |
| Error Parser.(LengthError length) -> | |
eprintf "Validation error: Length %d is out of bounds" length | |
| Error Parser.(HeightError height) -> | |
eprintf "Validation error: Height %d is out of bounds" height | |
| Ok tree -> | |
match Display.render tree with | |
| Error message -> eprintf "Display error: %s" message | |
| Ok output -> printf "%s" output | |
end | |
module Result_with_polymorhpic_variants_example (X: sig | |
type tree | |
module Parser : sig | |
type error = [ | |
| `ParserSyntaxError of int | |
| `ParserGrammarError of int * string | |
] | |
val parse : string -> (tree, [> error]) result | |
end | |
module Validation : sig | |
type error = [ | |
| `ValidationLengthError of int | |
| `ValidationHeightError of int | |
] | |
val perform : tree -> (tree, [> error]) result | |
end | |
module Display : sig | |
type error = [ | |
| `DisplayError of string | |
] | |
val render : tree -> (string, [> error]) result | |
end | |
end): sig | |
open X | |
val parse_and_validate : string -> (tree, [> | |
| `ParserSyntaxError of int | |
| `ParserGrammarError of int * string | |
| `ValidationLengthError of int | |
| `ValidationHeightError of int | |
]) result | |
val main : string -> (string, [> | |
| `ParserSyntaxError of int | |
| `ParserGrammarError of int * string | |
| `ValidationLengthError of int | |
| `ValidationHeightError of int | |
| `DisplayError of string | |
]) result | |
end = struct | |
open X | |
let parse_and_validate source = | |
let* tree = Parser.parse source in | |
Validation.perform tree | |
let main source = | |
let* tree = Parser.parse source in | |
let* tree = Validation.perform tree in | |
Display.render tree | |
let handle_errors source = | |
match main source with | |
| Ok output -> | |
printf "%s" output | |
| Error (`ParserSyntaxError line) -> | |
eprintf "Syntax error at line %d" line | |
| Error (`ParserGrammarError (line, message)) -> | |
eprintf "Grammar error at line %d: %s" line message | |
| Error (`ValidationLengthError length) -> | |
eprintf "Validation error: length %d is out of bounds" length | |
| Error (`ValidationHeightError height) -> | |
eprintf "Validation error: height %d is out of bounds" height | |
| Error (`DisplayError message) -> | |
eprintf "Display error: %s" message | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment