Header menu logo structured_programming_in_fsharp

Exception vs Result

An exception happens after the violation of a precondition in our code. For example, in the code below y ≠ 0 is a precondition:

let x = stdin.ReadLine() |> int
let y = stdin.ReadLine() |> int
let r = x / y
printfn $"{x} / {y} = {r}"

We also know that in some situations it is better to treat the error as any other value than to throw an exception. So the question is, do we represent an error as a value or do we throw an exception?

My way of answering such dilemma is: can the abnormal situation be followed by operations in the same domain where it occurred or do we have to leave it?

In the example above after y = 0 there is no calculation allowing us to continue, it's the user who should know that y = 0 is not part of the domain of the operation. So it makes sense to catch the exception or if possible to never let such value enter that scope.

Sometimes we discover that our domain can be enriched with values representing abnormal situations, and that way we can continue operating within it. However, in some cases, adding a Result type doesn't change the fact the only thing we can do is leaving one or more scopes.

In those instances an exception is more appropriate because adding Result is only making more cumbersome our way out.

Originally posted on 2023/10/21 on Twitter

val x: int
val stdin<'T> : System.IO.TextReader
Multiple items
val int: value: 'T -> int (requires member op_Explicit)

--------------------
type int = int32

--------------------
type int<'Measure> = int
val y: int
val r: int
val printfn: format: Printf.TextWriterFormat<'T> -> 'T

Type something to start searching.