using System.Collections.Generic;
public class TestADT : ADTInstance { IADTInstance Make() => new TestADT(); }
public class TestADT1 : ADTInstance {}
public static void Main()
var T1 = ADT.Make("T1", ADT.With(
ADT.For("Test", () => new TestADT())
Console.WriteLine("Hello World");
Dictionary<string,Func<IADTParams,IADTInstance>> Ctors {get;}
public static class ADT {
public static IADT Make(string kind, Dictionary<string, Func<IADTParams,IADTInstance>> map) {
public static Dictionary<string,Func<IADTParams,IADTInstance>> With (params KeyValuePair<string,Func<IADTParams,IADTInstance>>[] kvps) {
var dict = new Dictionary<string, Func<IADTParams,IADTInstance>>();
foreach(var kvp in kvps) {
dict.Add(kvp.Key, kvp.Value);
public static KeyValuePair<string,Func<IADTParams,IADTInstance>> For<T>(string tag, Func<IADTParams, IADTInstance> ctor)
return new KeyValuePair<string,Func<IADTParams, IADTInstance>>(tag, ctor);
public interface IADTParams {
bool IsFor(IADTInstance instance);
public interface IADTInstance {
public abstract class ADTInstance : IADTInstance {
public abstract IADTInstance Make();
public virtual string Tag => GetType().Name;
public abstract class ADTInstance<T> : ADTInstance, IADTInstance<T> where T: IADTParams {
public abstract IADTInstance<T> Make(T parameters);
public interface IADTInstance<T> : IADTInstance
IADTInstance<T> Make(T parameters);
public static class IADTXts {
public static string DEFAULT => "DEFAULT_ADT_STRING";
public static T Match<T> (
Dictionary<string, Func<IADTInstance,T>> dict) {
if(dict.ContainsKey(@this.Tag)) {
return dict[@this.Tag](@this);
} else if(dict.ContainsKey(DEFAULT)) {
return dict[DEFAULT](@this);
} else throw new Exception(
string.Format("Expected one of {0}, but recieved {1}",
(acc, next) => acc + ", " + next
public static object ToType<T> (this object obj, T type) {
var instance = Activator.CreateInstance(Type.GetType(type.ToString()));
foreach(PropertyInfo info in obj.GetType().GetProperties()) {
instance.GetType().GetProperty(info.Name).SetValue(instance, info.GetValue(obj, null), null);