CCCPaste

C# Tree+Traverse+ForAll

using LanguageExt;

public struct Node<T> where T : IComparable
{
public List<Node<T>> Children;
public T Val { get; set; }
public Node(T val)
{
Val = val;
Children = new List<Node<T>>();
}
public Node<T> Insert(Node<T> node)
{
if (!node.Val.Equals(Val))
Children.Add(node);
return this;
}

public void Print()
{
Console.WriteLine($"[ {Val} ]");
if (Children.Count > 0)
{
Console.WriteLine($"Children of {Val} / total={Children.Count}:");
foreach (Node<T> child in Children)
child.Print();
}
}
}

public static partial class Node
{
public static Node<TResult>
Traverse<T, TResult>(this Node<T> source, Func<T, TResult> f)
where T : IComparable
where TResult : IComparable
{
Node<TResult> result = new(f(source.Val));
foreach (Node<T> child in source.Children)
result.Children.Add(Traverse<T, TResult>(child, f));
return result;
}

public static void
ForAll<SrcT, AccT> (this Node<SrcT> source, Action<SrcT, AccT> f, AccT result)
where SrcT : IComparable
{
f(source.Val, result);
foreach (Node<SrcT> child in source.Children)
ForAll(child, f, result);
}
}

class Program
{
public static async Task<Either<Exception, string>>
TryLoadCommentAsync(HttpClient client, int id)
{
try
{
return await client.GetStringAsync($"http://kit.local/comment/?id={id}");
}
catch (HttpRequestException e)
{
return e;
}
}

public static Either<List<Exception>, Node<Either<Exception, string>>>
TryLoadComments(Node<int> tree)
{
using HttpClient client = new();

/* traverse tree */
var IdToResult = (int x) =>
{
var task = TryLoadCommentAsync(client, x);
return task.Result;
};
var commentTree = Node.Traverse(tree, IdToResult);

/* exceptions */
List<Exception> errList = new();
var CollectExceptions = (Either<Exception, string> val, List<Exception> result) =>
{
if (val.IsLeft)
result.Add((Exception)val); /* really */
};

Node.ForAll(commentTree, CollectExceptions, errList);

if (errList.Length() > 0)
return errList;

return commentTree;
}

public static void Main()
{
/* create tree */
Node<int> a = new(100);
Node<int> b = new(101);
Node<int> c = new(102);

Node<int> bb = new(1000);
b.Insert(bb);

Node<int> tree = new(10);
tree.Insert(a).Insert(b).Insert(c);

Node<int> root = new(1);
root.Insert(tree);

Console.WriteLine("Source:");
root.Print();

var result = TryLoadComments(root);
Console.WriteLine("Result:");
if (result.IsRight)
((Node<Either<Exception, string>>)result) /* really */
.Print();
else
((List<Exception>)result)
.ForEach((Exception e) => { Console.WriteLine(e.ToString()); });
}
}