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()); });
}
}