-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
a54805e
commit 9a291e4
Showing
10 changed files
with
359 additions
and
120 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
using System; | ||
|
||
namespace Moonad | ||
{ | ||
public sealed class ChoiceValueException : NullReferenceException | ||
{ | ||
public ChoiceValueException() : base("Choice value unavailable. Please check another choice.") { } | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,85 +1,15 @@ | ||
using System; | ||
|
||
namespace Moonad | ||
namespace Moonad | ||
{ | ||
public abstract class Choice<T1, T2> : IEquatable<Choice<T1, T2>> where T1 : notnull where T2 : notnull | ||
{ | ||
public bool IsChoice1 => this is Choice1; | ||
public bool IsChoice2 => this is Choice2; | ||
|
||
public T1 Choice1Of2 => GetChoice1(); | ||
public T2 Choice2Of2 => GetChoice2(); | ||
|
||
private Choice() { } | ||
|
||
public sealed class Choice1(T1 value) : Choice<T1, T2> | ||
{ | ||
internal T1 Value { get; } = value; | ||
} | ||
|
||
public sealed class Choice2(T2 value) : Choice<T1, T2> | ||
{ | ||
internal T2 Value { get; } = value; | ||
} | ||
|
||
public static implicit operator Choice<T1, T2>(T1 choice1) => | ||
new Choice1(choice1); | ||
|
||
public static implicit operator Choice<T1, T2>(T2 choice2) => | ||
new Choice2(choice2); | ||
|
||
public static implicit operator T1(Choice<T1, T2> choice) => | ||
choice.GetChoice1(); | ||
|
||
public static implicit operator T2(Choice<T1, T2> choice) => | ||
choice.GetChoice2(); | ||
|
||
private T1 GetChoice1() => | ||
((Choice1)this).Value; | ||
|
||
private T2 GetChoice2() => | ||
((Choice2)this).Value; | ||
|
||
public static bool operator == (Choice<T1,T2> left, Choice<T1, T2> right) => | ||
left.Equals(right); | ||
|
||
public static bool operator !=(Choice<T1, T2> left, Choice<T1, T2> right) => | ||
!left.Equals(right); | ||
|
||
public bool Equals(Choice<T1, T2>? other) | ||
{ | ||
if(other is null) | ||
return false; | ||
|
||
if(this is Choice1 && other is Choice1 choice1) | ||
return GetChoice1().Equals(choice1.Value); | ||
|
||
if (this is Choice2 && other is Choice2 choice2) | ||
return GetChoice2().Equals(choice2.Value); | ||
|
||
return false; | ||
} | ||
|
||
public override bool Equals(object? obj) | ||
{ | ||
if(obj is null || obj is not Choice<T1, T2> other) | ||
return false; | ||
public interface IChoice { } | ||
|
||
return Equals(other); | ||
} | ||
public readonly struct Choice<T>(T value) : IChoice where T : notnull | ||
{ | ||
private readonly T Choosed = value; | ||
|
||
public override int GetHashCode() | ||
{ | ||
return this is Choice1 | ||
? GetChoice1().GetHashCode() | ||
: GetChoice2().GetHashCode(); | ||
} | ||
public static implicit operator T(Choice<T> choice) => | ||
choice.Choosed; | ||
|
||
public override string ToString() | ||
{ | ||
return this is Choice1 | ||
? $"{nameof(Choice1)} {GetChoice1()}" | ||
: $"{nameof(Choice2)} {GetChoice2()}"; | ||
} | ||
public override string ToString() => | ||
Choosed.ToString(); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
using System; | ||
|
||
namespace Moonad | ||
{ | ||
public readonly struct Choice<T1, T2> : IChoice, IEquatable<Choice<T1, T2>> where T1 : notnull where T2 : notnull | ||
{ | ||
public readonly IChoice Choosed; | ||
|
||
public Choice(T1 choice) => | ||
Choosed = new Choice<T1>(choice); | ||
|
||
public Choice(T2 choice) => | ||
Choosed = new Choice<T2>(choice); | ||
|
||
public static implicit operator Choice<T1, T2>(T1 choice) => | ||
new(choice); | ||
|
||
public static implicit operator Choice<T1, T2>(T2 choice) => | ||
new(choice); | ||
|
||
public static implicit operator T1(Choice<T1, T2> choice) => | ||
(Choice<T1>)choice.Choosed; | ||
|
||
public static implicit operator T2(Choice<T1, T2> choice) => | ||
(Choice<T2>)choice.Choosed; | ||
|
||
public static bool operator ==(Choice<T1, T2> left, Choice<T1, T2> right) => | ||
left.Equals(right); | ||
|
||
public static bool operator !=(Choice<T1, T2> left, Choice<T1, T2> right) => | ||
!left.Equals(right); | ||
|
||
public bool Equals(Choice<T1, T2> other) | ||
{ | ||
if (Choosed is Choice<T1> choice1 && other.Choosed is Choice<T1>) | ||
return choice1.Equals(other.Choosed); | ||
|
||
if (Choosed is Choice<T2> choice2 && other.Choosed is Choice<T2>) | ||
return choice2.Equals(other.Choosed); | ||
|
||
return false; | ||
} | ||
|
||
public override bool Equals(object? obj) | ||
{ | ||
if (obj is null || obj is not Choice<T1, T2> other) | ||
return false; | ||
|
||
return Equals(other); | ||
} | ||
|
||
public override int GetHashCode() | ||
{ | ||
return Choosed switch | ||
{ | ||
Choice<T1> choice => choice.GetHashCode(), | ||
Choice<T2> choice => choice.GetHashCode(), | ||
_ => throw new ChoiceValueException() | ||
}; | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
using System; | ||
|
||
namespace Moonad | ||
{ | ||
public readonly struct Choice<T1, T2, T3> : IChoice, IEquatable<Choice<T1, T2, T3>> | ||
where T1 : notnull where T2 : notnull where T3 : notnull | ||
{ | ||
public readonly IChoice Choosed; | ||
|
||
public Choice(T1 choice) => | ||
Choosed = new Choice<T1>(choice); | ||
|
||
public Choice(T2 choice) => | ||
Choosed = new Choice<T2>(choice); | ||
|
||
public Choice(T3 choice) => | ||
Choosed = new Choice<T3>(choice); | ||
|
||
public static implicit operator Choice<T1, T2, T3>(T1 choice) => | ||
new(choice); | ||
|
||
public static implicit operator Choice<T1, T2, T3>(T2 choice) => | ||
new(choice); | ||
|
||
public static implicit operator Choice<T1, T2, T3>(T3 choice) => | ||
new(choice); | ||
|
||
public static implicit operator T1(Choice<T1, T2, T3> choice) => | ||
(Choice<T1>)choice.Choosed; | ||
|
||
public static implicit operator T2(Choice<T1, T2, T3> choice) => | ||
(Choice<T2>)choice.Choosed; | ||
|
||
public static implicit operator T3(Choice<T1, T2, T3> choice) => | ||
(Choice<T3>)choice.Choosed; | ||
|
||
public static bool operator ==(Choice<T1, T2, T3> left, Choice<T1, T2, T3> right) => | ||
left.Equals(right); | ||
|
||
public static bool operator !=(Choice<T1, T2, T3> left, Choice<T1, T2, T3> right) => | ||
!left.Equals(right); | ||
|
||
public bool Equals(Choice<T1, T2, T3> other) | ||
{ | ||
if (Choosed is Choice<T1> choice1 && other.Choosed is Choice<T1>) | ||
return choice1.Equals(other.Choosed); | ||
|
||
if (Choosed is Choice<T2> choice2 && other.Choosed is Choice<T2>) | ||
return choice2.Equals(other.Choosed); | ||
|
||
if (Choosed is Choice<T3> choice3 && other.Choosed is Choice<T3>) | ||
return choice3.Equals(other.Choosed); | ||
|
||
return false; | ||
} | ||
|
||
public override bool Equals(object? obj) | ||
{ | ||
if (obj is null || obj is not Choice<T1, T2, T3> other) | ||
return false; | ||
|
||
return Equals(other); | ||
} | ||
|
||
public override int GetHashCode() | ||
{ | ||
return Choosed switch | ||
{ | ||
Choice<T1> choice => choice.GetHashCode(), | ||
Choice<T2> choice => choice.GetHashCode(), | ||
Choice<T3> choice => choice.GetHashCode(), | ||
_ => throw new ChoiceValueException() | ||
}; | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,89 @@ | ||
using System; | ||
|
||
namespace Moonad | ||
{ | ||
public readonly struct Choice<T1, T2, T3, T4> : IChoice, IEquatable<Choice<T1, T2, T3, T4>> | ||
where T1 : notnull where T2 : notnull where T3 : notnull where T4 : notnull | ||
{ | ||
public readonly IChoice Choosed; | ||
|
||
public Choice(T1 choice) => | ||
Choosed = new Choice<T1>(choice); | ||
|
||
public Choice(T2 choice) => | ||
Choosed = new Choice<T2>(choice); | ||
|
||
public Choice(T3 choice) => | ||
Choosed = new Choice<T3>(choice); | ||
|
||
public Choice(T4 choice) => | ||
Choosed = new Choice<T4>(choice); | ||
|
||
public static implicit operator Choice<T1, T2, T3, T4>(T1 choice) => | ||
new(choice); | ||
|
||
public static implicit operator Choice<T1, T2, T3, T4>(T2 choice) => | ||
new(choice); | ||
|
||
public static implicit operator Choice<T1, T2, T3, T4>(T3 choice) => | ||
new(choice); | ||
|
||
public static implicit operator Choice<T1, T2, T3, T4>(T4 choice) => | ||
new(choice); | ||
|
||
public static implicit operator T1(Choice<T1, T2, T3, T4> choice) => | ||
(Choice<T1>)choice.Choosed; | ||
|
||
public static implicit operator T2(Choice<T1, T2, T3, T4> choice) => | ||
(Choice<T2>)choice.Choosed; | ||
|
||
public static implicit operator T3(Choice<T1, T2, T3, T4> choice) => | ||
(Choice<T3>)choice.Choosed; | ||
|
||
public static implicit operator T4(Choice<T1, T2, T3, T4> choice) => | ||
(Choice<T4>)choice.Choosed; | ||
|
||
public static bool operator ==(Choice<T1, T2, T3, T4> left, Choice<T1, T2, T3, T4> right) => | ||
left.Equals(right); | ||
|
||
public static bool operator !=(Choice<T1, T2, T3, T4> left, Choice<T1, T2, T3, T4> right) => | ||
!left.Equals(right); | ||
|
||
public bool Equals(Choice<T1, T2, T3, T4> other) | ||
{ | ||
if (Choosed is Choice<T1> choice1 && other.Choosed is Choice<T1>) | ||
return choice1.Equals(other.Choosed); | ||
|
||
if (Choosed is Choice<T2> choice2 && other.Choosed is Choice<T2>) | ||
return choice2.Equals(other.Choosed); | ||
|
||
if (Choosed is Choice<T3> choice3 && other.Choosed is Choice<T3>) | ||
return choice3.Equals(other.Choosed); | ||
|
||
if (Choosed is Choice<T4> choice4 && other.Choosed is Choice<T4>) | ||
return choice4.Equals(other.Choosed); | ||
|
||
return false; | ||
} | ||
|
||
public override bool Equals(object? obj) | ||
{ | ||
if (obj is null || obj is not Choice<T1, T2, T3, T4> other) | ||
return false; | ||
|
||
return Equals(other); | ||
} | ||
|
||
public override int GetHashCode() | ||
{ | ||
return Choosed switch | ||
{ | ||
Choice<T1> choice => choice.GetHashCode(), | ||
Choice<T2> choice => choice.GetHashCode(), | ||
Choice<T3> choice => choice.GetHashCode(), | ||
Choice<T4> choice => choice.GetHashCode(), | ||
_ => throw new ChoiceValueException() | ||
}; | ||
} | ||
} | ||
} |
Oops, something went wrong.