languageext eitherasyn 与聚合绑定与验证
languageext eitherasyn with aggegrate bind with validation
我在 c# 中使用 lauthy 语言 ext 这里有 3 个函数将在主函数中调用
目的是 return 命令的聚合结果.. 或错误但是当我将 y 传递给 ExecuteSingleHostCommands
Error CS1503 Argument 1: cannot convert from
'System.Func>'
to
'System.Func>' 03'
Returns 给定命令的乐趣
使用参数和 return 结果或错误执行乐趣
验证和 return 错误失败
-- Main func - 一个接一个地执行命令,如果有任何命令是错误的,则退出。如果一切顺利return 所有命令的汇总结果
内部静态函数> GetSingleCommands(
IDictionary>> commandMap,
命令 hostCommand) =>
commandMap.Where(命令 => command.Key == hostCommand.Name).Select(keyValuePairs => keyValuePairs.Value).FirstOrDefault();
内部静态 EitherAsync> ExecuteSingleCommands(
Func> 命令,字符串 hostCommand) =>
新列表>> {命令}.Aggregate(
右>(ImmutableList.Empty).ToAsync(),
(state, func) => state.Bind(response => func(hostCommand).Map(response.Add)));
internal static Either<Error, Unit> Validate(string hostCommand) =>
CommandMap.Find(command => command.Key == hostCommand).IsSome ? Right(Unit.Default) : Left<Error, Unit>(new Error());
public static EitherAsync<Error, ImmutableList<Response>> ExecuteAllAsync(
IDictionary<string, Func<string, EitherAsync<Error, HostResponse>>> commandMap, IList<Command> hostCommands) =>
from hostCommand in hostCommands
from x in Command.Validate(hostCommand.Name)
let y = Command.GetSingleHostCommands(commandMap, hostCommand).ToAsync()
select Command.ExecuteSingleHostCommands(y, hostCommand.jobName);
我认为你应该多注意这个问题。几乎不可能理解你在这里问什么,而且缺少函数 GetSingleHostCommands
和类型(你甚至拼错了我的名字 ;) )
无论如何,从你的例子中我可以推断出你有几个问题:
在 ExecuteAllAsync
中,您在一个 LINQ 表达式中混合了多个 monadic 类型。这不是 LINQ 或 monad 的工作方式。您必须始终尝试保持相同的单子类型。所以,hostCommands
是一个 IEnumerable
monad,Command.Validate(hostCommand.Name)
是一个 Either
monad
由于 Response
和 HostResponse
的结果类型,您似乎遇到了重复问题。这可以做成通用的。
GetSingleCommands
不会使用字典,因为它每次都会遍历它。
ExecuteSingleCommands
做了太多工作。它所要做的就是使用提供的命令调用委托。
看来您想多了,您可能想尝试退后一步并简化您的方法。函数式编程要记住的一件事是 始终遵循类型 。类型将始终引导您了解真相。
所以,首先要做的就是解决这个问题。这是我完成的一个实现,我认为它非常符合您的意图。我已经删除了对 lanuguage-ext Map
使用 Dictionary
和对语言扩展 Seq
使用 IList
和 ImmutableList
。主要是因为它们更易于使用,而且在代码中也更易于查看。
public class Command {
public readonly string Name;
static Either<Error, Func<string, EitherAsync<Error, R>>> GetCommand<R>(
Map<string, Func<string, EitherAsync<Error, R>>> commandMap,
Command hostCommand) =>
commandMap.Find(hostCommand.Name)
.ToEither(new Error());
internal static EitherAsync<Error, R> ExecuteCommand<R>(
Func<string, EitherAsync<Error, R>> command,
Command cmd) =>
command(cmd.Name);
static Either<Error, Unit> Validate<R>(
Map<string, Func<string, EitherAsync<Error, R>>> commandMap,
Command hostCommand) =>
commandMap.Find(hostCommand.Name)
.Map(_ => unit)
.ToEither(new Error());
public static EitherAsync<Error, Seq<R>> ExecuteAllAsync<R>(
Map<string, Func<string, EitherAsync<Error, R>>> commandMap,
Seq<Command> hostCommands) =>
hostCommands.Map(cmd =>
from _ in Command.Validate(commandMap, cmd).ToAsync()
from f in Command.GetCommand<R>(commandMap, cmd).ToAsync()
from r in Command.ExecuteCommand(f, cmd)
select r)
.Sequence();
}
您可能会从 ExecuteAllAsync
中注意到,现在正在映射 hostCommands
,在单个命令上使用内部 LINQ 表达式 运行。这将运行验证,然后获取命令,然后执行它,然后 returns 结果。
另请注意,LINQ 表达式的前两行使用 .ToAsync()
将其结果从 Either
转换为 EitherAsync
。因此,LINQ 表达式的每一行都使用相同的 monad:EitherAsync
.
地图将收集到 Seq<EitherAsync<Error, R>>
,这是函数的错误结果,EitherAsync
在 内部 Seq
,但我们希望它在 外面 。这就是对 .Sequence()
的调用所做的。它将 Seq<EitherAsync<Error, R>>
变成 EitherAsync<Error, Seq<R>>
.
我在 c# 中使用 lauthy 语言 ext 这里有 3 个函数将在主函数中调用 目的是 return 命令的聚合结果.. 或错误但是当我将 y 传递给 ExecuteSingleHostCommands
Error CS1503 Argument 1: cannot convert from 'System.Func>' to 'System.Func>' 03'
Returns 给定命令的乐趣
使用参数和 return 结果或错误执行乐趣
验证和 return 错误失败 -- Main func - 一个接一个地执行命令,如果有任何命令是错误的,则退出。如果一切顺利return 所有命令的汇总结果
内部静态函数> GetSingleCommands( IDictionary>> commandMap, 命令 hostCommand) => commandMap.Where(命令 => command.Key == hostCommand.Name).Select(keyValuePairs => keyValuePairs.Value).FirstOrDefault();
内部静态 EitherAsync> ExecuteSingleCommands( Func> 命令,字符串 hostCommand) => 新列表>> {命令}.Aggregate( 右>(ImmutableList.Empty).ToAsync(), (state, func) => state.Bind(response => func(hostCommand).Map(response.Add)));
internal static Either<Error, Unit> Validate(string hostCommand) => CommandMap.Find(command => command.Key == hostCommand).IsSome ? Right(Unit.Default) : Left<Error, Unit>(new Error()); public static EitherAsync<Error, ImmutableList<Response>> ExecuteAllAsync( IDictionary<string, Func<string, EitherAsync<Error, HostResponse>>> commandMap, IList<Command> hostCommands) => from hostCommand in hostCommands from x in Command.Validate(hostCommand.Name) let y = Command.GetSingleHostCommands(commandMap, hostCommand).ToAsync() select Command.ExecuteSingleHostCommands(y, hostCommand.jobName);
我认为你应该多注意这个问题。几乎不可能理解你在这里问什么,而且缺少函数 GetSingleHostCommands
和类型(你甚至拼错了我的名字 ;) )
无论如何,从你的例子中我可以推断出你有几个问题:
在
ExecuteAllAsync
中,您在一个 LINQ 表达式中混合了多个 monadic 类型。这不是 LINQ 或 monad 的工作方式。您必须始终尝试保持相同的单子类型。所以,hostCommands
是一个IEnumerable
monad,Command.Validate(hostCommand.Name)
是一个Either
monad由于
Response
和HostResponse
的结果类型,您似乎遇到了重复问题。这可以做成通用的。GetSingleCommands
不会使用字典,因为它每次都会遍历它。ExecuteSingleCommands
做了太多工作。它所要做的就是使用提供的命令调用委托。
看来您想多了,您可能想尝试退后一步并简化您的方法。函数式编程要记住的一件事是 始终遵循类型 。类型将始终引导您了解真相。
所以,首先要做的就是解决这个问题。这是我完成的一个实现,我认为它非常符合您的意图。我已经删除了对 lanuguage-ext Map
使用 Dictionary
和对语言扩展 Seq
使用 IList
和 ImmutableList
。主要是因为它们更易于使用,而且在代码中也更易于查看。
public class Command {
public readonly string Name;
static Either<Error, Func<string, EitherAsync<Error, R>>> GetCommand<R>(
Map<string, Func<string, EitherAsync<Error, R>>> commandMap,
Command hostCommand) =>
commandMap.Find(hostCommand.Name)
.ToEither(new Error());
internal static EitherAsync<Error, R> ExecuteCommand<R>(
Func<string, EitherAsync<Error, R>> command,
Command cmd) =>
command(cmd.Name);
static Either<Error, Unit> Validate<R>(
Map<string, Func<string, EitherAsync<Error, R>>> commandMap,
Command hostCommand) =>
commandMap.Find(hostCommand.Name)
.Map(_ => unit)
.ToEither(new Error());
public static EitherAsync<Error, Seq<R>> ExecuteAllAsync<R>(
Map<string, Func<string, EitherAsync<Error, R>>> commandMap,
Seq<Command> hostCommands) =>
hostCommands.Map(cmd =>
from _ in Command.Validate(commandMap, cmd).ToAsync()
from f in Command.GetCommand<R>(commandMap, cmd).ToAsync()
from r in Command.ExecuteCommand(f, cmd)
select r)
.Sequence();
}
您可能会从 ExecuteAllAsync
中注意到,现在正在映射 hostCommands
,在单个命令上使用内部 LINQ 表达式 运行。这将运行验证,然后获取命令,然后执行它,然后 returns 结果。
另请注意,LINQ 表达式的前两行使用 .ToAsync()
将其结果从 Either
转换为 EitherAsync
。因此,LINQ 表达式的每一行都使用相同的 monad:EitherAsync
.
地图将收集到 Seq<EitherAsync<Error, R>>
,这是函数的错误结果,EitherAsync
在 内部 Seq
,但我们希望它在 外面 。这就是对 .Sequence()
的调用所做的。它将 Seq<EitherAsync<Error, R>>
变成 EitherAsync<Error, Seq<R>>
.