如何将 Validation<string, Unit> 转换为成功时为空的字符串?
How do I convert a Validation<string, Unit> to a string that's empty on success?
我是函数式编程的新手,我正在尝试在一个非常命令的代码库中工作,所以我正在尝试编写主要是 FP 但不能完全的代码。
我必须为以下方法编写覆盖...
protected override string CreateEntity(XElement xe)
...其中 xe
包含数据库更新所需的两条数据。该方法需要验证 xe
的内容,然后进行更新,returning "" 成功或管道分隔的错误列表。
我借鉴了language-ext测试中的credit card validation sample,写了一些辅助方法,如下所示(实现与示例非常相似,因此省略)...
private Validation<string, int> ValidateRegionID(XElement xe)
在示例中,他对这些集合使用了 Apply,returned 一个 Validation
如果一切正常,它就是新的信用卡对象,或者 Error
如果不。就我而言,如果一切顺利(因为我正在更新数据库,而不是创建新对象),我没有任何要 return 的东西,所以就这样...
Validation<string, Unit> validation = (ValidateRegionID(xe), ValidateClinAppsID(xe))
.Apply((regionID, clinAppsID) =>
{
// Do the database update (yes, impure code)...
return Unit.Default;
});
我不知道这是否是最好的方法,欢迎提出任何建议。
我更大的问题是下一步该怎么做。以下作品,但在我看来不是很优雅或 FP...
return validation.IsFail
? string.Join("|", validation.FailAsEnumerable())
: "";
有更好的方法吗?
如果验证失败,您可以简单地抛出异常。
以后调用您的代码的任何人都可以对其应用异常处理。
另一种选择是发送错误代码而不是消息。在这种情况下,被调用方可以将每个错误代码转换为特定错误。
代码的最后一部分(格式错误)可以这样完成:
[Fact]
void Test()
{
Validation<string, Unit> resultFromDatabase = Fail<string, Unit>("error");
var showError1 = string.Join("|", resultFromDatabase.FailToSeq()); // use the fact that FailToSeq() will return empty seq for success
var showError2 = string.Join("|", resultFromDatabase.IfSuccess(Seq<string>())); // explicitly supply a value of the error type (Seq<string>) for success case
var showError3 = resultFromDatabase.Match(_ => "", errors => string.Join("|", errors)); // only call string.Join for errors
}
选择你最喜欢的变体。如果你想拥有干净的代码/不依赖 FailToSeq() 实现来处理这两种情况,你应该使用 Match
或 IfSuccess
/IfFail
.[=16= 明确处理这两种情况]
如果你想改进你的整体设计(避免不纯的代码),你可能必须改变一些基本的东西。一个(非常 FP)选项是使用 Free Monad,并且 LanguageExt 取得了进展,使之变得更容易,但这可能是转换传统 OO 代码库的一大步。参见:
https://github.com/louthy/language-ext/releases/tag/3.4.11(使用 CodeGen 的免费 Monad)
https://github.com/louthy/language-ext/wiki/Thinking-Functionally:-Application-Architecture
我是函数式编程的新手,我正在尝试在一个非常命令的代码库中工作,所以我正在尝试编写主要是 FP 但不能完全的代码。
我必须为以下方法编写覆盖...
protected override string CreateEntity(XElement xe)
...其中 xe
包含数据库更新所需的两条数据。该方法需要验证 xe
的内容,然后进行更新,returning "" 成功或管道分隔的错误列表。
我借鉴了language-ext测试中的credit card validation sample,写了一些辅助方法,如下所示(实现与示例非常相似,因此省略)...
private Validation<string, int> ValidateRegionID(XElement xe)
在示例中,他对这些集合使用了 Apply,returned 一个 Validation
如果一切正常,它就是新的信用卡对象,或者 Error
如果不。就我而言,如果一切顺利(因为我正在更新数据库,而不是创建新对象),我没有任何要 return 的东西,所以就这样...
Validation<string, Unit> validation = (ValidateRegionID(xe), ValidateClinAppsID(xe))
.Apply((regionID, clinAppsID) =>
{
// Do the database update (yes, impure code)...
return Unit.Default;
});
我不知道这是否是最好的方法,欢迎提出任何建议。
我更大的问题是下一步该怎么做。以下作品,但在我看来不是很优雅或 FP...
return validation.IsFail
? string.Join("|", validation.FailAsEnumerable())
: "";
有更好的方法吗?
如果验证失败,您可以简单地抛出异常。 以后调用您的代码的任何人都可以对其应用异常处理。
另一种选择是发送错误代码而不是消息。在这种情况下,被调用方可以将每个错误代码转换为特定错误。
代码的最后一部分(格式错误)可以这样完成:
[Fact]
void Test()
{
Validation<string, Unit> resultFromDatabase = Fail<string, Unit>("error");
var showError1 = string.Join("|", resultFromDatabase.FailToSeq()); // use the fact that FailToSeq() will return empty seq for success
var showError2 = string.Join("|", resultFromDatabase.IfSuccess(Seq<string>())); // explicitly supply a value of the error type (Seq<string>) for success case
var showError3 = resultFromDatabase.Match(_ => "", errors => string.Join("|", errors)); // only call string.Join for errors
}
选择你最喜欢的变体。如果你想拥有干净的代码/不依赖 FailToSeq() 实现来处理这两种情况,你应该使用 Match
或 IfSuccess
/IfFail
.[=16= 明确处理这两种情况]
如果你想改进你的整体设计(避免不纯的代码),你可能必须改变一些基本的东西。一个(非常 FP)选项是使用 Free Monad,并且 LanguageExt 取得了进展,使之变得更容易,但这可能是转换传统 OO 代码库的一大步。参见:
https://github.com/louthy/language-ext/releases/tag/3.4.11(使用 CodeGen 的免费 Monad) https://github.com/louthy/language-ext/wiki/Thinking-Functionally:-Application-Architecture