Skip to content

Instantly share code, notes, and snippets.

@Stepami
Last active April 6, 2022 17:33
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Stepami/24acee3673f0e899cd5fc166d65cb0e2 to your computer and use it in GitHub Desktop.
Save Stepami/24acee3673f0e899cd5fc166d65cb0e2 to your computer and use it in GitHub Desktop.
в статье https://habr.com/ru/post/656919/ представленные структуры данных PairedHashSet и PairedList можно было представить таким сложным образом. Этот пример показывает, насколько некрасиво могут писаться простые вещи без higher-kinded polymorphism
public class PairedEnumerable<E, W, T>
where W : Wrapper<E, T>, new()
where E : IEnumerable<T>, new()
{
public W First { get; }
public W Second { get; }
public PairedEnumerable(E first, E second)
{
First = new W {Enumerable = first};
Second = new W {Enumerable = second};
}
public PairedEnumerable() :
this(new E(), new E())
{
}
private PairedEnumerable(E enumerable) :
this(enumerable, new E())
{
}
public void Deconstruct(out W first, out W second)
{
first = First;
second = Second;
}
public E Merge() =>
First.Except(Second).Enumerable;
public override string ToString()
=> string.Join("\n", Merge());
public static implicit operator PairedEnumerable<E, W, T>(E enumerable) =>
new(enumerable);
}
public abstract class Wrapper<E, T>
where E : IEnumerable<T>, new()
{
public E Enumerable { get; init; }
protected Wrapper(E enumerable)
{
Enumerable = enumerable;
}
public abstract Wrapper<E, T> Union(Wrapper<E, T> that);
public abstract Wrapper<E, T> Except(Wrapper<E, T> that);
}
public struct PairedEnumerableGroup<E, W, T> : IGroup<PairedEnumerable<E, W, T>>
where W : Wrapper<E, T>, new()
where E : IEnumerable<T>, new()
{
public PairedEnumerable<E, W, T> Plus(PairedEnumerable<E, W, T> left, PairedEnumerable<E, W, T> right)
{
var (left1, left2) = left;
var (right1, right2) = right;
var newLeft = left1.Except(right2).Union(right1.Except(left2));
var newRight = left2.Except(right1).Union(right2.Except(left1));
return new PairedEnumerable<E, W, T>(newLeft.Enumerable, newRight.Enumerable);
}
public PairedEnumerable<E, W, T> Zero => new();
public PairedEnumerable<E, W, T> Inverse(PairedEnumerable<E, W, T> item)
{
var (first, second) = item;
return new PairedEnumerable<E, W, T>(second.Enumerable, first.Enumerable);
}
}
public class ListWrapper<T> : Wrapper<List<T>, T>
{
public ListWrapper() : base(new List<T>())
{
}
private ListWrapper(List<T> list) : base(list)
{
}
public override Wrapper<List<T>, T> Union(Wrapper<List<T>, T> that)
{
var list = new List<T>(Enumerable);
list.AddRange(that.Enumerable);
return new ListWrapper<T>(list);
}
public override Wrapper<List<T>, T> Except(Wrapper<List<T>, T> that)
{
var list = new List<T>(Enumerable);
that.Enumerable.ForEach(item => list.Remove(item));
return new ListWrapper<T>(list);
}
}
public class HashSetWrapper<T> : Wrapper<HashSet<T>, T>
{
public HashSetWrapper() : this(new HashSet<T>())
{
}
private HashSetWrapper(HashSet<T> hashSet) : base(hashSet)
{
}
public override Wrapper<HashSet<T>, T> Union(Wrapper<HashSet<T>, T> that)
{
var hashSet = new HashSet<T>(Enumerable);
hashSet.UnionWith(that.Enumerable);
return new HashSetWrapper<T>(hashSet);
}
public override Wrapper<HashSet<T>, T> Except(Wrapper<HashSet<T>, T> that)
{
var hashSet = new HashSet<T>(Enumerable);
hashSet.ExceptWith(that.Enumerable);
return new HashSetWrapper<T>(hashSet);
}
}
public static class Groups
{
public static IGroup<PairedEnumerable<List<T>, ListWrapper<T>, T>> PairedListGroup<T>() =>
default(PairedEnumerableGroup<List<T>, ListWrapper<T>, T>);
public static IGroup<PairedEnumerable<HashSet<T>, HashSetWrapper<T>, T>> PairedHashSetGroup<T>() =>
default(PairedEnumerableGroup<HashSet<T>, HashSetWrapper<T>, T>);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment