Last active
April 6, 2022 17:33
-
-
Save Stepami/24acee3673f0e899cd5fc166d65cb0e2 to your computer and use it in GitHub Desktop.
в статье https://habr.com/ru/post/656919/ представленные структуры данных PairedHashSet и PairedList можно было представить таким сложным образом. Этот пример показывает, насколько некрасиво могут писаться простые вещи без higher-kinded polymorphism
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
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