diff --git a/.gitignore b/.gitignore index af4d2e7..0d590ee 100644 --- a/.gitignore +++ b/.gitignore @@ -28,4 +28,5 @@ x64/ *.log *.vspscc *.vssscc -.builds \ No newline at end of file +.builds +.fake \ No newline at end of file diff --git a/Sanchime.Functional/Extensions/Option.cs b/Sanchime.Functional/Extensions/Option.cs index add671c..62ca2b6 100644 --- a/Sanchime.Functional/Extensions/Option.cs +++ b/Sanchime.Functional/Extensions/Option.cs @@ -7,11 +7,11 @@ public static class OptionExtension #region 函子: 同一范畴内不同对象之间的态射 - public static Option Map(this None _, Func mapping) - => Option.None; + // public static Option Map(this None _, Func mapping) + // => Option.None; - public static Option Map(this Some some, Func mapping) - => Option.Some(mapping(some.Value)); + // public static Option Map(this Some some, Func mapping) + // => Option.Some(mapping(some.Value)); public static Option Map(this Option option, Func mapping) => option.Match(() => Option.None, (val) => Option.Some(mapping(val))); diff --git a/Sanchime.Functional/Products/Either.cs b/Sanchime.Functional/Products/Eithers/Either.cs similarity index 69% rename from Sanchime.Functional/Products/Either.cs rename to Sanchime.Functional/Products/Eithers/Either.cs index b0c357e..c3f09c1 100644 --- a/Sanchime.Functional/Products/Either.cs +++ b/Sanchime.Functional/Products/Eithers/Either.cs @@ -8,7 +8,7 @@ public static class Either => new(right); } -public readonly struct Either +public readonly partial struct Either : IEither { internal TLeft? Left { get; } internal TRight? Right { get; } @@ -48,28 +48,3 @@ public readonly struct Either public override string ToString() => Match(l => $"Left({l})", r => $"Right({r})"); } - -public readonly struct Left -{ - internal TLeft Value { get; } - internal Left(TLeft value) - => Value = value; - public override string ToString() - => $"Left({Value})"; -} - -public readonly struct Right -{ - internal TRight Value { get; } - internal Right(TRight value) - => Value = value; - - public override string ToString() - => $"Right({Value})"; - - public Right Map(Func mapping) - => Either.Right(mapping(Value)); - - public Either Bind(Func> binding) - => binding(Value); -} \ No newline at end of file diff --git a/Sanchime.Functional/Products/Eithers/IEither.cs b/Sanchime.Functional/Products/Eithers/IEither.cs new file mode 100644 index 0000000..998c3f7 --- /dev/null +++ b/Sanchime.Functional/Products/Eithers/IEither.cs @@ -0,0 +1,16 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace Sanchime.Functional.Products; + +public interface IEither : IEither, IFunctor +{ + +} + +public interface IEither +{ + +} \ No newline at end of file diff --git a/Sanchime.Functional/Products/Eithers/Left.cs b/Sanchime.Functional/Products/Eithers/Left.cs new file mode 100644 index 0000000..7f6a9bf --- /dev/null +++ b/Sanchime.Functional/Products/Eithers/Left.cs @@ -0,0 +1,10 @@ +namespace Sanchime.Functional.Products; + +public readonly struct Left : IEither +{ + internal TLeft Value { get; } + internal Left(TLeft value) + => Value = value; + public override string ToString() + => $"Left({Value})"; +} diff --git a/Sanchime.Functional/Products/Eithers/Right.cs b/Sanchime.Functional/Products/Eithers/Right.cs new file mode 100644 index 0000000..e92ac8b --- /dev/null +++ b/Sanchime.Functional/Products/Eithers/Right.cs @@ -0,0 +1,17 @@ +namespace Sanchime.Functional.Products; + +public readonly struct Right : IEither +{ + internal TRight Value { get; } + internal Right(TRight value) + => Value = value; + + public override string ToString() + => $"Right({Value})"; + + public Right Map(Func mapping) + => Either.Right(mapping(Value)); + + public Either Bind(Func> binding) + => binding(Value); +} \ No newline at end of file diff --git a/Sanchime.Functional/Products/IApplicative.cs b/Sanchime.Functional/Products/IApplicative.cs index bd86207..79fd63e 100644 --- a/Sanchime.Functional/Products/IApplicative.cs +++ b/Sanchime.Functional/Products/IApplicative.cs @@ -4,6 +4,13 @@ namespace Sanchime.Functional.Products; /// 应用函子 /// /// -public interface IApplicative : IFunctor +public interface IApplicative : IApplicative, IFunctor + where TCategory : ICategory { } + + +public interface IApplicative : IFunctor +{ + +} \ No newline at end of file diff --git a/Sanchime.Functional/Products/IFunctor.cs b/Sanchime.Functional/Products/IFunctor.cs index 7d46b0f..e7a87be 100644 --- a/Sanchime.Functional/Products/IFunctor.cs +++ b/Sanchime.Functional/Products/IFunctor.cs @@ -5,17 +5,14 @@ namespace Sanchime.Functional.Products; /// 同一范畴内不同对象之间的映射 /// /// -public interface IFunctor : ICategory +public interface IFunctor : IFunctor + where TCategory : ICategory { - TCategory Map(Func mapping); + TCategory Map(Func mapping); } -public struct Test : IFunctor> +public interface IFunctor : ICategory { - public T? Value {get; set; } - public Test Map(Func, Test> mapping) - { - return mapping(this); - } -} + +} \ No newline at end of file diff --git a/Sanchime.Functional/Products/IMonad.cs b/Sanchime.Functional/Products/IMonad.cs index d68cf1f..8debbde 100644 --- a/Sanchime.Functional/Products/IMonad.cs +++ b/Sanchime.Functional/Products/IMonad.cs @@ -5,5 +5,6 @@ namespace Sanchime.Functional.Products; /// /// public interface IMonad : IApplicative + where TCategory : ICategory { } diff --git a/Sanchime.Functional/Products/Options/IOption.cs b/Sanchime.Functional/Products/Options/IOption.cs new file mode 100644 index 0000000..a1036ae --- /dev/null +++ b/Sanchime.Functional/Products/Options/IOption.cs @@ -0,0 +1,16 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace Sanchime.Functional.Products; + +public interface IOption : ICategory +{ + +} + +public interface IOption : IOption +{ + TValue Value { get; } +} \ No newline at end of file diff --git a/Sanchime.Functional/Products/Options/None.cs b/Sanchime.Functional/Products/Options/None.cs new file mode 100644 index 0000000..296590c --- /dev/null +++ b/Sanchime.Functional/Products/Options/None.cs @@ -0,0 +1,9 @@ +namespace Sanchime.Functional.Products; + +/// +/// 状态 +/// +public readonly partial struct None : IOption +{ + internal static readonly None Default = new(); +} diff --git a/Sanchime.Functional/Products/Options/NoneFunctor.cs b/Sanchime.Functional/Products/Options/NoneFunctor.cs new file mode 100644 index 0000000..8ad6310 --- /dev/null +++ b/Sanchime.Functional/Products/Options/NoneFunctor.cs @@ -0,0 +1,12 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace Sanchime.Functional.Products; + +public readonly partial struct None : IFunctor +{ + public None Map(Func mapping) + => Option.None; +} \ No newline at end of file diff --git a/Sanchime.Functional/Products/Option.cs b/Sanchime.Functional/Products/Options/Option.cs similarity index 82% rename from Sanchime.Functional/Products/Option.cs rename to Sanchime.Functional/Products/Options/Option.cs index ef10a16..f75ce5d 100644 --- a/Sanchime.Functional/Products/Option.cs +++ b/Sanchime.Functional/Products/Options/Option.cs @@ -1,30 +1,12 @@ namespace Sanchime.Functional.Products; -/// -/// 状态 -/// -public readonly struct None -{ - internal static readonly None Default = new(); -} - -/// -/// 状态 -/// -/// -public readonly struct Some -{ - internal TValue Value { get; } - internal Some(TValue value) => Value = value ?? throw new ArgumentNullException(nameof(value), "不能在Some状态中包装null值, 应该使用None"); -} - public static class Option { public static None None => None.Default; public static Option Some(TValue value) => new Some(value); } -public readonly struct Option : IEquatable, IEquatable> +public readonly partial struct Option : IOption, IEquatable, IEquatable> { private readonly TValue _value; diff --git a/Sanchime.Functional/Products/Options/OptionFunctor.cs b/Sanchime.Functional/Products/Options/OptionFunctor.cs new file mode 100644 index 0000000..94c0e01 --- /dev/null +++ b/Sanchime.Functional/Products/Options/OptionFunctor.cs @@ -0,0 +1,11 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace Sanchime.Functional.Products.Options; + +public readonly partial struct Option //: IFunctor +{ + +} \ No newline at end of file diff --git a/Sanchime.Functional/Products/Options/Some.cs b/Sanchime.Functional/Products/Options/Some.cs new file mode 100644 index 0000000..897ba0e --- /dev/null +++ b/Sanchime.Functional/Products/Options/Some.cs @@ -0,0 +1,14 @@ +namespace Sanchime.Functional.Products; + +/// +/// 状态 +/// +/// +public readonly struct Some : IOption, IFunctor +{ + internal TValue Value { get; } + internal Some(TValue value) => Value = value ?? throw new ArgumentNullException(nameof(value), "不能在Some状态中包装null值, 应该使用None"); + + public Option> Map(Func> mapping) + => Option.Some(mapping(this.Value)); +}