dotnet / dotnet/fsharp

Eliminate union case remapping common in monadic functions

Open
#15,872 7 comments 0 reactions 0 assignees View on GitHub
Area-Compiler-Optimization Feature Request Theme-Performance
Dominant language
F#
Stars
4.3k
Forks
876
Avg merge
4d 22h
Merged PRs (30d)
144

Description

Consider an inlined version of `Result.map`

```fsharp
let inline map mapping result =
match result with
| Error e -> Error e
| Ok x -> Ok (mapping x)

let ff x = map (fun y -> y.ToString ()) x

let ffs x = map id x
```

The last 2 functions compiled down to

```csharp
public static FSharpResult ff(FSharpResult x)
{
if (x.Tag == 0)
{
a resultValue = x.ResultValue;
a a = resultValue;
return FSharpResult.NewOk(a.ToString());
}
return FSharpResult.NewError(x.ErrorValue);
}

public static FSharpResult ffs(FSharpResult x)
{
if (x.Tag == 0)
{
return FSharpResult.NewOk(x.ResultValue);
}
return FSharpResult.NewError(x.ErrorValue);
}
```

In both functions a new error case is allocated. This is necessary in `ff` (and in the original `map`), because the input result type is `Result<'a, 'b>` and the output is `Result`. However, input and output types are the same in `ffs`, so the original union case can simply pass through instead of being recreated.

```csharp
public static FSharpResult ffs(FSharpResult x)
{
if (x.Tag == 0)
{
return FSharpResult.NewOk(x.ResultValue);
}
return x; // <---------
}
```

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.