I have this code which is purely for experimentation and not used for anything real.
(I realise that the code can be simplified – see below – but that’s not the point of my current exercise.)
Note: The multiply and divide functions and their corresponding Error types have been removed for clarity(?)
The output I expect to get is of Result<float, ArithmeticError>
let basicAdd addend1 addend2 = addend1 + addend2
type AdditionError =
| AdditionOverflowError
| UnknownAdditionError
let add addend1 addend2 =
try
Ok (basicAdd addend1 addend2)
with
| :? System.OverflowException -> Error AdditionOverflowError
| _ -> Error UnknownAdditionError
type SubtractionError =
| SubtractionOverflowError
| UnknownSubtractionError
let basicSubtract minuend subtrahend = minuend - subtrahend
let subtract minuend subtrahend =
try
Ok (basicSubtract minuend subtrahend)
with
| :? System.OverflowException -> Error SubtractionOverflowError
| _ -> Error UnknownSubtractionError
type ArithmeticError =
| ArithmeticAdditionError of AdditionError
| ArithmeticSubtractionError of SubtractionError
let result =
Ok 20.0
|> Result.map (basicAdd 30.0)
|> Result.bind (add 100.0)
|> Result.bind (subtract 80.0)
I am getting a Type Mismatch error on the last line, because a SubtractionError is not an AdditionError, and that’s understandable.
However, I cannot find a way to get the subtraction to work.
I tried adding
|> Result.mapError ArithmeticAdditionError
…before the last line but that just changes the error into a slightly different one.
I tried exchanging the last line for
|> subtract 80.0
…but that’s no better.
I tried using
|> Result.map (subtract 80.0)
…but that gives me a Result<Result<>> which is no good.
I just can’t seem to get my head around what I’m supposed to do with this.
I thought I had a tiny grasp on this area until I came up with this problem.
Can anyone help?
Am I missing something very simple?
Is this something that I need to be using computational expressions for? (I really don’t want to get into those just yet if I can help it.)
I know the code can be simplified by re-coding as something like
let basicAdd addend1 addend2 = addend1 + addend2
let basicSubtract minuend subtrahend = minuend - subtrahend
type ArithmeticError =
| OverflowError
| UnknownError
let errorify f operand1 operand2 =
try
Ok (f operand1 operand2)
with
| :? System.OverflowException -> Error OverflowError
| _ -> Error UnknownError
let add = errorify basicAdd
let subtract = errorify basicSubtract
let result =
Ok 20.0
|> Result.map (basicAdd 30.0)
|> Result.bind (add 100.0)
|> Result.bind (subtract 80.0)
…and it works, but I’m trying to treat the two arithmetic operations as things from different systems that I can’t modify, as could happen in real life.