diff --git a/.idea/.idea.Sanchime/.idea/.gitignore b/.idea/.idea.Sanchime/.idea/.gitignore
new file mode 100644
index 0000000..999f71a
--- /dev/null
+++ b/.idea/.idea.Sanchime/.idea/.gitignore
@@ -0,0 +1,13 @@
+# Default ignored files
+/shelf/
+/workspace.xml
+# Rider ignored files
+/contentModel.xml
+/projectSettingsUpdater.xml
+/modules.xml
+/.idea.Sanchime.iml
+# Editor-based HTTP Client requests
+/httpRequests/
+# Datasource local storage ignored files
+/dataSources/
+/dataSources.local.xml
diff --git a/.idea/.idea.Sanchime/.idea/.name b/.idea/.idea.Sanchime/.idea/.name
new file mode 100644
index 0000000..104cc73
--- /dev/null
+++ b/.idea/.idea.Sanchime/.idea/.name
@@ -0,0 +1 @@
+Sanchime
\ No newline at end of file
diff --git a/.idea/.idea.Sanchime/.idea/encodings.xml b/.idea/.idea.Sanchime/.idea/encodings.xml
new file mode 100644
index 0000000..df87cf9
--- /dev/null
+++ b/.idea/.idea.Sanchime/.idea/encodings.xml
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file
diff --git a/.idea/.idea.Sanchime/.idea/indexLayout.xml b/.idea/.idea.Sanchime/.idea/indexLayout.xml
new file mode 100644
index 0000000..7b08163
--- /dev/null
+++ b/.idea/.idea.Sanchime/.idea/indexLayout.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/.idea.Sanchime/.idea/vcs.xml b/.idea/.idea.Sanchime/.idea/vcs.xml
new file mode 100644
index 0000000..35eb1dd
--- /dev/null
+++ b/.idea/.idea.Sanchime/.idea/vcs.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Sanchime.Functional/Extensions/Dictionary.cs b/Sanchime.Functional/Extensions/Dictionary.cs
index 4c09738..6bd8513 100644
--- a/Sanchime.Functional/Extensions/Dictionary.cs
+++ b/Sanchime.Functional/Extensions/Dictionary.cs
@@ -6,5 +6,5 @@ namespace Sanchime.Functional.Extensions;
public static class DictionaryExtension
{
public static Option Lookup(this Dictionary dictionary, K key) where K: notnull
- => dictionary.TryGetValue(key, out T? value) ? Option.Some(value) : Option.None;
+ => dictionary.TryGetValue(key, out T? value) ? Optional.Some(value) : Optional.None;
}
diff --git a/Sanchime.Functional/Extensions/Enum.cs b/Sanchime.Functional/Extensions/Enum.cs
index 28fd95d..d06babc 100644
--- a/Sanchime.Functional/Extensions/Enum.cs
+++ b/Sanchime.Functional/Extensions/Enum.cs
@@ -3,8 +3,8 @@ namespace Sanchime.Functional.Extensions;
public static class EnumExtension
{
///
- /// 将字符串转换为相应的枚举值的
public static Option Parse(this string @this) where T : struct
- => Enum.TryParse(@this, out T val) ? Option.Some(val) : Option.None;
+ => Enum.TryParse(@this, out T val) ? Optional.Some(val) : Optional.None;
}
diff --git a/Sanchime.Functional/Extensions/IEnumerable.cs b/Sanchime.Functional/Extensions/IEnumerable.cs
index 2400e68..857de0b 100644
--- a/Sanchime.Functional/Extensions/IEnumerable.cs
+++ b/Sanchime.Functional/Extensions/IEnumerable.cs
@@ -11,7 +11,7 @@ public static class IEnumerableExtension
public static Func> Return() => t => List(t);
///
- /// 将序列内第一条元素转换为
+ /// 将序列内第一条元素转换为
///
///
///
@@ -20,14 +20,14 @@ public static class IEnumerableExtension
{
if (source is null)
{
- return Option.None;
+ return Optional.None;
}
var first = source.FirstOrDefault();
- return first is not null ? Option.Some(first) : Option.None;
+ return first is not null ? Optional.Some(first) : Optional.None;
}
///
- /// 给定谓词,查询序列内第一条数据并将其转换为
+ /// 给定谓词,查询序列内第一条数据并将其转换为
///
/// 数据源
/// 谓词
@@ -37,14 +37,14 @@ public static class IEnumerableExtension
{
if (source is null)
{
- return Option.None;
+ return Optional.None;
}
var first = source.Where(predicate).FirstOrDefault();
- return first is not null ? Option.Some(first) : Option.None;
+ return first is not null ? Optional.Some(first) : Optional.None;
}
///
- /// 将序列内最后一个元素转换为
+ /// 将序列内最后一个元素转换为
///
///
///
@@ -53,14 +53,14 @@ public static class IEnumerableExtension
{
if (source is null)
{
- return Option.None;
+ return Optional.None;
}
var tail = source.LastOrDefault();
- return tail is not null ? Option.Some(tail) : Option.None;
+ return tail is not null ? Optional.Some(tail) : Optional.None;
}
///
- /// 给定谓词,查询序列内最后一条数据并将其转换为
+ /// 给定谓词,查询序列内最后一条数据并将其转换为
///
/// 数据源
/// 谓词
@@ -70,10 +70,10 @@ public static class IEnumerableExtension
{
if (source is null)
{
- return Option.None;
+ return Optional.None;
}
var last = source.Where(predicate).LastOrDefault();
- return last is not null ? Option.Some(last) : Option.None;
+ return last is not null ? Optional.Some(last) : Optional.None;
}
public static R Match(this IEnumerable source, Func Empty, Func, R> Otherwise)
diff --git a/Sanchime.Functional/Extensions/Nullable.cs b/Sanchime.Functional/Extensions/Nullable.cs
index 9ff820f..0328d05 100644
--- a/Sanchime.Functional/Extensions/Nullable.cs
+++ b/Sanchime.Functional/Extensions/Nullable.cs
@@ -3,8 +3,8 @@ namespace Sanchime.Functional.Extensions;
public static class NullableExtension
{
///
- /// 将值转换为
+ /// 将值转换为
///
public static Option ToOption(this Nullable @this) where T : struct
- => @this.HasValue ? Option.Some(@this.Value) : Option.None;
+ => @this.HasValue ? Optional.Some(@this.Value) : Optional.None;
}
diff --git a/Sanchime.Functional/Extensions/Option.cs b/Sanchime.Functional/Extensions/Option.cs
index d802293..63bcaf9 100644
--- a/Sanchime.Functional/Extensions/Option.cs
+++ b/Sanchime.Functional/Extensions/Option.cs
@@ -2,8 +2,7 @@ namespace Sanchime.Functional.Extensions;
public static class OptionExtension
{
- public static Unit Match(this Option option, Action None, Action Some)
- => option.Match(None.ToFunc(), Some.ToFunc());
+
#region 函子: 同一范畴内不同对象之间的态射
@@ -13,27 +12,18 @@ public static class OptionExtension
// 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)));
+ // public static Option Map(this Option option, Func mapping)
+ // => option.Match(() => Option.None, (val) => Option.Some(mapping(val)));
- // public static Option> Map(this Option option, Func mapping)
+ // public static IOption Map(this Option option, Func mapping)
// => option.Map(mapping.Curry());
- // public static Option> Map(this Option option, Func mapping)
+ // public static IOption Map(this Option option, Func mapping)
// => option.Map(mapping.CurryFirst());
#endregion
#region 单子: 自函子范畴上的幺半群
- ///
- /// Return自然变换: 将上下文无关的值导入至上下文有关的世界
- ///
- ///
- ///
- ///
- public static Option Return(T value)
- => value is null ? Option.None : Option.Some(value);
-
public static Option Bind(this Option option, Func> binding)
=> option.Match(() => new Option(), binding);
@@ -46,12 +36,12 @@ public static class OptionExtension
// #region 应用函子
- // public static Option Apply(this Option> option, Option value)
- // => option.Match(
- // None: () => Option.None,
- // Some: (apply) => value.Match(
- // None: () => Option.None,
- // Some: (val) => Option.Some(apply(val))));
+ public static Option Apply(this Option> option, Option value)
+ => option.Match(
+ None: () => Optional.None,
+ Some: (apply) => value.Match(
+ None: () => Optional.None,
+ Some: (val) => Optional.Some(apply(val))));
// public static Option> Apply(this Option> option, Option value)
// => option.Map(CurryingExtension.Curry).Apply(value);
@@ -95,7 +85,7 @@ public static class OptionExtension
=> left.Match(() => right(), (_) => left);
///
- /// 将
+ /// 将
///
///
///
@@ -111,18 +101,18 @@ public static class OptionExtension
#region Linq式
- // public static Option Select(this Option source, Func mapping)
- // => source.Map(mapping);
+ public static IOption Select(this Option source, Func mapping)
+ => source.Map(mapping);
public static Option Where(this Option source, Func predicate)
- => source.Match(() => Option.None, (val) => predicate(val) ? source : Option.None);
+ => source.Match(() => Optional.None, (val) => predicate(val) ? source : Optional.None);
public static Option SelectMany(this Option source, Func> binding, Func project)
=> source.Match(
- None: () => Option.None,
+ None: () => Optional.None,
Some: (val) => binding(val).Match(
- None: () => Option.None,
- Some: (res) => Option.Some(project(val, res))));
+ None: () => Optional.None,
+ Some: (res) => Optional.Some(project(val, res))));
#endregion
diff --git a/Sanchime.Functional/Products/Eithers/IEither.cs b/Sanchime.Functional/Products/Eithers/IEither.cs
index 5d96db9..7297271 100644
--- a/Sanchime.Functional/Products/Eithers/IEither.cs
+++ b/Sanchime.Functional/Products/Eithers/IEither.cs
@@ -10,7 +10,7 @@ public interface IEither : IEither
}
-public interface IEither : IFunctor
+public interface IEither
{
}
\ No newline at end of file
diff --git a/Sanchime.Functional/Products/IApplicative.cs b/Sanchime.Functional/Products/IApplicative.cs
deleted file mode 100644
index 79fd63e..0000000
--- a/Sanchime.Functional/Products/IApplicative.cs
+++ /dev/null
@@ -1,16 +0,0 @@
-namespace Sanchime.Functional.Products;
-
-///
-/// 应用函子
-///
-///
-public interface IApplicative : IApplicative, IFunctor
- where TCategory : ICategory
-{
-}
-
-
-public interface IApplicative : IFunctor
-{
-
-}
\ No newline at end of file
diff --git a/Sanchime.Functional/Products/ICategory.cs b/Sanchime.Functional/Products/ICategory.cs
deleted file mode 100644
index 339204b..0000000
--- a/Sanchime.Functional/Products/ICategory.cs
+++ /dev/null
@@ -1,6 +0,0 @@
-namespace Sanchime.Functional.Products;
-
-public interface ICategory
-{
-
-}
diff --git a/Sanchime.Functional/Products/IFunctor.cs b/Sanchime.Functional/Products/IFunctor.cs
deleted file mode 100644
index c17ebf1..0000000
--- a/Sanchime.Functional/Products/IFunctor.cs
+++ /dev/null
@@ -1,24 +0,0 @@
-namespace Sanchime.Functional.Products;
-
-///
-/// 函子
-/// 同一范畴内不同对象之间的映射
-///
-///
-public interface IFunctor : IFunctor
- where TCategory : ICategory
-{
- TCategory Map(Func mapping);
-}
-
-public interface IFunctor : IFunctor
- where TCategory : ICategory
-{
- TCategory Map(Func mapping);
-}
-
-public interface IFunctor : ICategory
-{
- public TResult Map(Func mapping)
- => mapping(this);
-}
\ No newline at end of file
diff --git a/Sanchime.Functional/Products/IMonad.cs b/Sanchime.Functional/Products/IMonad.cs
deleted file mode 100644
index 8debbde..0000000
--- a/Sanchime.Functional/Products/IMonad.cs
+++ /dev/null
@@ -1,10 +0,0 @@
-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
index 57e4fe1..21ee327 100644
--- a/Sanchime.Functional/Products/Options/IOption.cs
+++ b/Sanchime.Functional/Products/Options/IOption.cs
@@ -5,12 +5,16 @@ using System.Threading.Tasks;
namespace Sanchime.Functional.Products;
-public interface IOption : IFunctor
+public interface IOption
{
bool IsSome { get; }
}
-public interface IOption : IOption, IFunctor
+///
+/// 选项
+///
+/// 选项内部维护的值
+public interface IOption : IOption
{
TValue Value { get; }
}
diff --git a/Sanchime.Functional/Products/Options/None.cs b/Sanchime.Functional/Products/Options/None.cs
index 5d9409f..556ca45 100644
--- a/Sanchime.Functional/Products/Options/None.cs
+++ b/Sanchime.Functional/Products/Options/None.cs
@@ -1,10 +1,14 @@
namespace Sanchime.Functional.Products;
///
-/// 的状态
+/// 的状态
///
public readonly partial struct None : IOption
{
+ ///
+ /// 静态构造形成单例
+ ///
+ static None() { }
public bool IsSome => false;
internal static readonly None Default = new();
}
diff --git a/Sanchime.Functional/Products/Options/NoneFunctor.cs b/Sanchime.Functional/Products/Options/NoneFunctor.cs
deleted file mode 100644
index 731498e..0000000
--- a/Sanchime.Functional/Products/Options/NoneFunctor.cs
+++ /dev/null
@@ -1,12 +0,0 @@
-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/Options/Option.cs b/Sanchime.Functional/Products/Options/Option.cs
index 13b89ed..2aa665a 100644
--- a/Sanchime.Functional/Products/Options/Option.cs
+++ b/Sanchime.Functional/Products/Options/Option.cs
@@ -1,6 +1,8 @@
+using Sanchime.Functional.Extensions;
+
namespace Sanchime.Functional.Products;
-public static class Option
+public static class Optional
{
public static None None => None.Default;
public static Option Some(TValue value) => new Some(value);
@@ -18,39 +20,39 @@ public readonly partial struct Option : IOption, IEquatable (_isSome, _value) = (true, value ?? throw new ArgumentNullException(nameof(value)));
///
- /// 将转换为
+ /// 将转换为
///
///
public static implicit operator Option(None _)
=> new();
///
- /// 将转换为
+ /// 将转换为
///
///
public static implicit operator Option(Some some)
=> new(some.Value);
///
- /// 将常规值提升至
+ /// 将常规值提升至
///
///
public static implicit operator Option(TValue value)
- => value is null ? Option.None : Option.Some(value);
-
- public bool IsSome => this.Match(() => false, (_) => true);
+ => value is null ? Optional.None : Optional.Some(value);
+
+ public bool IsSome => _isSome;
///
- /// 获取内部的值,如果为则抛出异常
+ /// 获取内部的值,如果为则抛出异常
///
///
public TValue ValueUnsafe => this.Match(() => throw new InvalidOperationException(), val => val);
///
- /// 获取内部的值,如果为则返回默认值
+ /// 获取内部的值,如果为则返回默认值
///
///
- public TValue Value => this.Match(() => default!, val => val);
+ public TValue Value => _isNone ? default! : _value;
///
/// 转换为序列
@@ -60,15 +62,7 @@ public readonly partial struct Option : IOption, IEquatable
- /// 接收两个函数,根据的状态进行求值
- ///
- ///
- /// None状态
- /// Some状态
- ///
- public TResult Match(Func None, Func Some)
- => _isSome ? Some(_value) : None();
+
public bool Equals(Option other)
=> this._isSome == other._isSome
diff --git a/Sanchime.Functional/Products/Options/OptionFunctor.cs b/Sanchime.Functional/Products/Options/OptionFunctor.cs
index eeb66bb..c9b2c55 100644
--- a/Sanchime.Functional/Products/Options/OptionFunctor.cs
+++ b/Sanchime.Functional/Products/Options/OptionFunctor.cs
@@ -2,18 +2,39 @@ using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
+using Sanchime.Functional.Extensions;
namespace Sanchime.Functional.Products;
-public readonly partial struct Option
+public static class OptionFunctor
{
+ ///
+ /// 接收两个函数,根据的状态进行求值
+ ///
+ ///
+ /// None状态
+ /// Some状态
+ ///
+ public static TResult Match(this IOption option, Func None, Func Some)
+ => option.IsSome ? Some(option.Value) : None();
+
+ public static Unit Match(this IOption option, Action None, Action Some)
+ => option.Match(None.ToFunc(), Some.ToFunc());
+
///
/// 映射
///
+ ///
///
+ ///
///
///
- public IOption Map(Func mapping)
- => this.Match(() => Option.None, value => Option.Some(mapping(value)));
+ public static IOption Map(this IOption option, Func mapping)
+ => option.Match(() => Optional.None, value => Optional.Some(mapping(value)));
+ public static IOption> Map(this IOption option,Func mapping)
+ => option.Map(mapping.Curry());
+
+ public static IOption> Map(this IOption option, Func mapping)
+ => option.Map(mapping.CurryFirst());
}
\ No newline at end of file
diff --git a/Sanchime.Functional/Products/Options/OptionMonad.cs b/Sanchime.Functional/Products/Options/OptionMonad.cs
new file mode 100644
index 0000000..3e3492d
--- /dev/null
+++ b/Sanchime.Functional/Products/Options/OptionMonad.cs
@@ -0,0 +1,16 @@
+namespace Sanchime.Functional.Products;
+
+public readonly partial struct Option
+{
+ ///
+ /// Return自然变换: 将上下文无关的值导入至上下文有关的世界
+ ///
+ ///
+ ///
+ ///
+ public static IOption Return(T value)
+ => value is null ? Optional.None : Optional.Some(value);
+
+ public static IOption Return(TValue value)
+ => Return(value);
+}
\ No newline at end of file
diff --git a/Sanchime.Functional/Products/Options/Some.cs b/Sanchime.Functional/Products/Options/Some.cs
index c6efb1a..450ee87 100644
--- a/Sanchime.Functional/Products/Options/Some.cs
+++ b/Sanchime.Functional/Products/Options/Some.cs
@@ -1,16 +1,15 @@
namespace Sanchime.Functional.Products;
///
-/// 的状态
+/// 的状态
///
///
-public readonly struct Some : IOption
+public readonly struct Some : IOption
{
public bool IsSome => Value is not null;
public TValue Value { get; }
internal Some(TValue value) => Value = value ?? throw new ArgumentNullException(nameof(value), "不能在Some状态中包装null值, 应该使用None");
-
public IOption Map(Func mapping)
- => Option.Some(mapping(this.Value));
+ => Optional.Some(mapping(this.Value));
}
diff --git a/Sanchime.Test/Program.cs b/Sanchime.Test/Program.cs
index 429c5eb..4f8fe00 100644
--- a/Sanchime.Test/Program.cs
+++ b/Sanchime.Test/Program.cs
@@ -3,38 +3,51 @@ using Sanchime.Functional.Extensions;
using Sanchime.Toolkits;
-void foo(Option option)
+try
{
- var res = option.Map(x => x + 2);
- res.WriteLine();
-}
-"预计打印Some(12)".WriteLine();
-foo(10);
-"预计打印None".WriteLine();
-foo(Option.None);
+ void foo(Option option)
+ {
+ var res = option.Map(x => x + 2);
+ res.WriteLine();
+ }
-"预计打印Char".WriteLine();
-Option.Some(1)
- .Map(x => (float)x + 1.2)
- .Map(x => x.ToString())
- .Map(x => x.GetType().Name)
- .ForEach(x => x.WriteLine());
+ "预计打印Some(12)".WriteLine();
+ foo(10);
+ "预计打印None".WriteLine();
+ foo(Optional.None);
+
+ "预计打印Some(String)".WriteLine();
+ Optional.Some(1)
+ .Map(x => x + 1.2)
+ .Map(x => x.ToString())
+ .Map(x => x.GetType().Name)
+ .WriteLine();
// 测试Option的Bind
-var parse = (string s) => Int32.TryParse(s, out int i) ? Option.Some(i) : Option.None;
-var foo1 = (string s) => s.Pipe(parse).Bind(Age.Of);
-
-foo1("111").WriteLine();
-foo1("aaa").WriteLine();
-foo1("123").WriteLine();
+ var parse = (string s) => Int32.TryParse(s, out int i) ? Optional.Some(i) : Optional.None;
+ var foo1 = (string s) => s.Pipe(parse).Bind(Age.Of);
+ "预计打印Some(111)".WriteLine();
+ foo1("111").WriteLine();
+ "预计打印None".WriteLine();
+ foo1("aaa").WriteLine();
+ "预计打印Some(123)".WriteLine();
+ foo1("123").WriteLine();
// 管道
-foo1("1ab").Pipe(x => Console.WriteLine(x));
+ "预计打印None".WriteLine();
+ foo1("1ab").Pipe(x => x.WriteLine());
+}
+catch (Exception ex)
+{
+ ex.Message.WriteLine();
+ ex.StackTrace.WriteLine();
+}
+
public struct Age
{
private int _value;
public static Option Of(int age)
- => IsValid(age) ? Option.Some(new Age(age)) : Option.None;
+ => IsValid(age) ? Optional.Some(new Age(age)) : Optional.None;
private Age(int age)
{
diff --git a/Sanchime.Toolkits/Basic.cs b/Sanchime.Toolkits/Basic.cs
index 217aed1..a15e98c 100644
--- a/Sanchime.Toolkits/Basic.cs
+++ b/Sanchime.Toolkits/Basic.cs
@@ -5,7 +5,7 @@ public static class Basic
{
public static void WriteLine(this T @this)
{
- Debug.WriteLine(@this);
+ Console.WriteLine(@this);
}
public static void WriteLine(this T @this, Func func)
diff --git a/Sanchime.sln.DotSettings.user b/Sanchime.sln.DotSettings.user
new file mode 100644
index 0000000..1460b21
--- /dev/null
+++ b/Sanchime.sln.DotSettings.user
@@ -0,0 +1,2 @@
+
+ True
\ No newline at end of file