W4k.Either
0.1.0-preview
See the version list below for details.
dotnet add package W4k.Either --version 0.1.0-preview
NuGet\Install-Package W4k.Either -Version 0.1.0-preview
<PackageReference Include="W4k.Either" Version="0.1.0-preview" />
paket add W4k.Either --version 0.1.0-preview
#r "nuget: W4k.Either, 0.1.0-preview"
// Install W4k.Either as a Cake Addin #addin nuget:?package=W4k.Either&version=0.1.0-preview&prerelease // Install W4k.Either as a Cake Tool #tool nuget:?package=W4k.Either&version=0.1.0-preview&prerelease
W4k.Either
This library provides a variety of types for handling the results of operations or representing discriminated unions of two or more types.
Installation
To install the library, add the following package reference to your project file:
<ItemGroup>
<PackageReference Include="W4k.Either" Version="0.1.0" />
</ItemGroup>
Description
Types provided by this library are intended to be used as return types of methods and functions. They are designed to be used in functional programming style, but can be used in any other style as well.
Type | Description |
---|---|
Either<TLeft, TRight> |
Discriminated union of two or more types |
Maybe<TValue> |
Optional value representation |
Result<TError> |
Result representation without a value |
Result<TValue, TError> |
Result representation with a value |
OptionalResult<TValue, TError> |
Optional result with a value (similar to Result<Maybe<TValue>, TError>) |
All types are generated using W4k.Either.CodeGeneration
package.
Usage
Common API for all provided types:
Method/Property | Description |
---|---|
ctor | Creates a new instance of the type with a value |
Case (property) |
Property for use with pattern matching (returns current value as object ) |
TryPick |
Allows retrieval of value from the type (if present) |
Bind<TNew> |
Binds the value to a new instance of type TNew using the binder function |
Map<TNew> |
Maps the value to a new value of type TNew using the mapper function |
Match<TResult> |
Handles all possible cases, returning TResult |
Match<TState, TResult> |
Handles all possible cases returning TResult using a state |
MatchAsync<TResult> |
Asynchronously handles all possible cases returning TResult |
MatchAsync<TState, TResult> |
Asynchronously handles all possible cases returning TResult using a state |
Switch |
Handles all possible cases (void ) |
Switch<TState> |
Handles all possible cases using a state |
SwitchAsync |
Asynchronously handles all possible cases |
SwitchAsync<TState> |
Asynchronously handles all possible cases using a state |
ToString |
Returns the string representation of the value |
GetHashCode |
Returns the hash code of the value |
Equals |
Compares equality between monads |
== and != |
Compares equality between monads |
conversion, implicit operator |
Enables implicit conversion from a value to a monad |
Either
Use Either
to communicate the result of an operation without propagating an exception.
Either<User, FetchError> GetUser(UserIdentifier userId)
{
try
{
// ...
return new User(...);
}
catch (Exception ex)
{
return new FetchError(ex);
}
}
var result = GetUser(userId);
var message = result.Match(
user => $"User {user.Name} fetched",
error => $"Error {error.Message} occured"
);
For Either<TLeft, TRight>
, there are additional properties for inspecting the state:
Method/Property | Description |
---|---|
IsLeft |
Returns true if value is of type TLeft , otherwise false |
IsRight |
Returns true if value is of type TRight , otherwise false |
Maybe
Use Maybe
to communicate that an operation resulted in no value, as an alternative to returning null
.
Maybe<User> FindUser(UserIdentifier userId)
{
// ...
return userFound
? new User(...) // or Maybe<User>.Some(new User(...))
: Maybe<User>.None;
}
var user = FindUser(...);
if (user.HasValue)
{
Console.WriteLine($"User found: {user.Value.Name}");
}
Method/Property | Description |
---|---|
HasValue |
Returns true if value is present, otherwise false |
Value |
Returns value if present, otherwise default |
static Maybe.Some<T>(T) |
Creates new instance of Maybe<T> with value |
static Maybe.None<T>() |
Creates new instance of Maybe<T> without value |
Result
To indicate the result of an operation without throwing exceptions or using tuples, use Result
.
This type is the same as Either<TValue, TError>
, but with additional properties to inspect the state of the result object.
Result<User, FetchError> GetUser(UserIdentifier userId)
{
try
{
// ...
return new User(...);
}
catch (Exception ex)
{
return new FetchError(ex);
}
}
var result = GetUser(userId);
if (result.IsSuccess)
{
Console.WriteLine($"User found: {result.Value.Name}");
}
else
{
Console.WriteLine($"Error {result.Error.Message} occured");
}
// ... or if you prefer errlang - I mean Go
var (user, err) = GetUser(userId);
if (err != null)
{
Environment.Exit(1);
}
Console.WriteLine($"User found: {user.Name}");
Method/Property | Description |
---|---|
IsSuccess |
Returns true if value is present, otherwise false |
IsFailed |
Returns true if error is present, otherwise false |
Value |
Returns value if present, otherwise throws exception |
Error |
Returns error if present, otherwise throws exception |
Deconstruct |
Deconstructs the result into two variables: value and error |
static Result.Success<TError>() |
Creates new instance of Result<TError> without value |
static Result.Success<TValue, TError>(TValue) |
Creates new instance of Result<TValue, TError> with value |
static Result.Failed<TError>(TError) |
Creates new instance of Result<TError> with error |
static Result.Failed<TValue, TError>(TError) |
Creates new instance of Result<TValue, TError> with error |
OptionalResult
OptionalResult
can indicate the result of an operation with an optional value. It's the same as Result<Maybe<TValue>, TError>
.
OptionalResult<User, FetchError> FindUser(UserIdentifier userId)
{
try
{
// ...
return userFound
? new User(...)
: OptionalResult<User>.Empty;
}
catch (Exception ex)
{
return new FetchError(ex);
}
}
var result = FindUser(userId);
if (result.IsSuccess)
{
if (result.HasValue)
{
Console.WriteLine($"User found: {result.Value.Name}");
}
else
{
Console.WriteLine("User not found");
}
}
else
{
Console.WriteLine($"Error {result.Error.Message} occured");
}
Method/Property | Description |
---|---|
IsSuccess |
Returns true if error is not present, otherwise false |
HasValue |
Returns true if value is present (implies IsSuccess ), otherwise false |
IsFailed |
Returns true if error is present, otherwise false |
Value |
Returns value if present, otherwise throws exception |
Error |
Returns error if present, otherwise throws exception |
Deconstruct |
Deconstructs the result into two variables: value and error |
static OptionalResult.Success<TError, TError>(TValue) |
Creates new instance of OptionalResult<TValue, TError> with value |
static OptionalResult.Empty<TValue, TError>() |
Creates new instance of OptionalResult<TValue, TError> without value |
static OptionalResult.Failed<TValue, TError>(TError) |
Creates new instance of OptionalResult<TValue, TError> with error |
Product | Versions Compatible and additional computed target framework versions. |
---|---|
.NET | net6.0 is compatible. net6.0-android was computed. net6.0-ios was computed. net6.0-maccatalyst was computed. net6.0-macos was computed. net6.0-tvos was computed. net6.0-windows was computed. net7.0 was computed. net7.0-android was computed. net7.0-ios was computed. net7.0-maccatalyst was computed. net7.0-macos was computed. net7.0-tvos was computed. net7.0-windows was computed. net8.0 was computed. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. |
-
net6.0
- No dependencies.
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
Version | Downloads | Last updated |
---|---|---|
1.1.1 | 475 | 11/4/2023 |
1.1.0 | 640 | 7/6/2023 |
1.0.0 | 580 | 7/1/2023 |
0.2.0-preview | 577 | 6/16/2023 |
0.1.0-preview | 533 | 6/10/2023 |