继从这个问题 https://stackoverflow.com/questions/53506325/result-vs-raise-in-f-async,我在组合不同类型时遇到问题Result
类型在一起。
(以下是一个人为的示例,不是真实的代码)
假设我有一个读取文件的函数:
type ReadFileError =
| FileNotFound of string
let readFile (path : string) : Result<string, ReadFileError> =
// --- 8< ---
以及一个以某种方式解析它的函数:
type JsonParseError =
| InvalidStructure of string
let parseJson (content : string) : Result<Json, JsonParseError> =
// --- 8< ---
现在我可以将它们组合起来创建一个读取和解析文件的函数:
type ReadJsonError =
| ReadFileError of ReadFileError
| JsonParseError of JsonParseError
let readJson (path : string) : Result<Json, ReadJsonError> =
match path |> readFile with
| Ok content ->
match content |> parseJson with
| Ok json -> Ok json
| Error e -> Error (ReadJsonError.JsonParseError e)
| Error e -> Error (ReadJsonError.ReadFileError e)
正如您所看到的,统一错误类型相当尴尬。我需要定义一个新的联合类型并包装Error
正确地一侧。对于基于异常的方法,您不必担心这一点,因为 throw 就类型而言是开放式的。
是否有可能使Result
组合不同类型错误时的样式是否方便?
组合错误类型是一个问题Result
我只是在尝试时才意识到这一点。
除了异常之外,这可以通过让所有异常继承基类来“解决”。所以一种类似的方法可能是type R<'T> = Result<'T, exn>
但是,我发现这没有吸引力,并且通常会陷入一种模式,即我定义自己的结果类型,该类型允许同质类型的聚合失败。
有点像这样
type BadResult = Message of string | Exception of exn
type BadTree = Leaf of BadResult | Fork of BadTree*BadTree
type R<'T> = Good of 'T | Bad of BadTree
另一种方法可能是结合Result
失败使用Choice
。不确定一个人最终会因为这个而进入一个特别有吸引力的地方。
let bind (t : Result<'T, 'TE>) (uf 'T -> Result<'U, 'UE>) : Result<'U, Choice<'TE, 'TU>> = ...
这可能根本对您没有帮助,但也许它会产生一些关于如何继续的想法?
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)