Open kerams opened 1 year ago
I've had a look at how this could be implemented in Optimizer.fs. Unfortunately, it isn't immediately obvious that a union construction expression arises from a match clause like | Error e -> Error e
, because the original match expression undergoes significant changes during pattern compilation. In theory we could always replace a union construction expression in the form Case (old.Field1, old.Field2)
provided that the type of this expression and old
is the same and all fields are supplied from old
in the right order.
This would mean that even
let copy = Case (old.Field1, old.Field2)
would be turned into
let copy = old
which is perfectly OK thanks to union immutability, but is problematic when someone relies on reference (in)equality.
@kerams Reference equality is already an issue in your original optimisation.
Indeed, but you have no choice - | e -> e
doesn't fly, even though the author might have liked that.
@kerams or you can investigate making that syntax work.
If that syntax can work, then more complex cases of returning the original may also work:
let inline map mapping result =
match result with
| Ok x -> Ok (mapping x)
| (Error e) as x ->
printfn $"This error is {e}"
x
That does work already and constrains mapping
to 'a -> 'a
.
Ah then this path won't work. Nevermind.
Consider an inlined version of
Result.map
The last 2 functions compiled down to
In both functions a new error case is allocated. This is necessary in
ff
(and in the originalmap
), because the input result type isResult<'a, 'b>
and the output isResult<string, 'b>
. However, input and output types are the same inffs
, so the original union case can simply pass through instead of being recreated.