Skip to content

Commit

Permalink
refactor: new Choices!
Browse files Browse the repository at this point in the history
  • Loading branch information
wsantosdev committed Jan 13, 2024
1 parent a54805e commit 9a291e4
Show file tree
Hide file tree
Showing 10 changed files with 359 additions and 120 deletions.
Binary file modified icon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
9 changes: 9 additions & 0 deletions src/Choice/Choice.Exceptions.cs
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.") { }
}
}
88 changes: 9 additions & 79 deletions src/Choice/Choice.cs
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();
}
}
62 changes: 62 additions & 0 deletions src/Choice/ChoiceT1T2.cs
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()
};
}
}
}
76 changes: 76 additions & 0 deletions src/Choice/ChoiceT1T2T3.cs
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()
};
}
}
}
89 changes: 89 additions & 0 deletions src/Choice/ChoiceT1T2T3T4.cs
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()
};
}
}
}
Loading

0 comments on commit 9a291e4

Please sign in to comment.