添加免费单子

This commit is contained in:
Sanchime 2022-05-14 18:43:04 +08:00
parent c26fb69188
commit bd9392ec50
2 changed files with 95 additions and 0 deletions

View File

@ -0,0 +1,75 @@
using Sanchime.Functional.Extensions;
using static Sanchime.Functional.Extensions.TaskExtension;
namespace Sanchime.Functional.Monads;
public abstract class Free<T>
{
public abstract R Match<R>(Func<T, R> Done, Func<Coyo<object, Free<T>>, R> More);
}
internal sealed class Done<T> : Free<T>
{
public T Value { get; }
public Done(T value)
=> Value = value;
public override R Match<R>(Func<T, R> Done, Func<Coyo<object, Free<T>>, R> More)
=> Done(Value);
}
internal sealed class More<T> : Free<T>
{
public Coyo<object, Free<T>> Next { get; }
public More(Coyo<object, Free<T>> next)
=> Next = next;
public override R Match<R>(Func<T, R> Done, Func<Coyo<object, Free<T>>, R> More)
=> More(Next);
}
/// <summary>
/// 自由单子
/// </summary>
public static class FreeMonad
{
/// <summary>
/// 自然变幻Return 将值导入至Free的世界
/// </summary>
/// <param name="value">无状态的值</param>
/// <typeparam name="T"></typeparam>
/// <returns></returns>
public static Free<T> Return<T>(T value)
=> Done(value);
/// <summary>
/// 执行Free
/// </summary>
/// <param name="free">计算描述</param>
/// <param name="interpret">解释执行</param>
/// <typeparam name="T"></typeparam>
/// <returns></returns>
public static T Run<T>(this Free<T> free, Func<object, object> interpret)
=> free.Match(val => val, coyo => Run(coyo.Func(interpret(coyo.Value)), interpret));
/// <summary>
/// 异步执行Free
/// </summary>
/// <param name="free">计算描述</param>
/// <param name="interpret">解释执行</param>
/// <typeparam name="T"></typeparam>
/// <returns></returns>
public static Task<T> Run<T>(this Free<T> free, Func<object, Task<object>> interpret)
=> free.Match<Task<T>>(val => Async(val), async coyo => await Run(coyo.Func(await interpret(coyo.Value)),interpret));
public static Free<T> Of<T>(object op)
=> More(Coyo.Of<object, T>(op).Map(val => Done<T>(val)));
internal static Free<T> Done<T>(T value)
=> new Done<T>(value);
internal static Free<T> More<T>(Coyo<object, Free<T>> value)
=> new More<T>(value);
}

View File

@ -0,0 +1,20 @@
namespace Sanchime.Functional.Products;
public readonly struct Coyo<V, T>
{
public V Value {get;}
public Func<object, T> Func { get; }
public Coyo(V value, Func<object, T> func)
=> (Value, Func) = (value, func);
}
public static class Coyo
{
public static Coyo<V, T> Of<V, T>(V value)
=> new Coyo<V, T>(value, x => (T)x);
public static Coyo<V, R> Map<V, T, R>(this Coyo<V, T> @this, Func<T, R> mapping)
=> new Coyo<V, R>(@this.Value, x => mapping(@this.Func(x)));
}