f# - 在可区分联合中对结果类型进行编码

标签 f#

我有多个代码块,它们可以以不可恢复的错误结束,可以通过用户输入取消,或者以其他方式为下一个代码块提供输入值。那么如何处理最后一步,即成功(所有计算均成功完成)。

type Res<'T> =
| Next of 'T
| Cancel
| Fail of string

module Res =
    let bind arg f =
        match arg with
        | Next x -> f x
        | Cancel -> Cancel
        | Fail x -> Fail x

我现在可以像这样将这些步骤串在一起,唉,类型 Res 具有特殊的含义。

let (|?>) = Res.bind

firstFunc() 
|?> fun intermediateResult ->
    secondFunc intermediateResult
    ...
    |?> fun otherResult ->
        lastFunc otherResult
|> function
| Fail msg -> printfn "Error: %s" msg
| Cancel -> printfn "Cancelled"
| Next() -> printfn "Succeeded"

如果我将 Success 编码为离散替代方案,我将在最后一个子句中遇到额外的情况 Next _。解决这个问题的首选方法是什么?

最佳答案

我认为您的 Next of 'TSuccess of 'T 代表几乎相同的事情 - 它们意味着计算 block 完成并返回了一些值。出于可组合性的原因,计算 block 是否是整个链中的最后一个并不重要——原则上,计算 block 的行为应该是相同的,无论它是在开头还是在结尾您的管道。

但是,如果您想区分这两种情况(并且如果这不会影响组成 block 时的属性),那么我可能会使用带有附加标志的 Success 情况:

type ResultKind = Success | Next
type Result<'T> =
  | Completed of 'T * ResultKind
  | Cancel
  | Fail of string

现在您可以使用 Completed(42, Success) 创建最终值(并使用 Completed(42, Next) 创建即时结果)。

在模式匹配中,您可以忽略该标志,只需编写 |已完成(结果,_)-> ...

关于f# - 在可区分联合中对结果类型进行编码,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18960075/

相关文章:

debugging - 如何诊断 F# 交互中的故障源

f# - 从 F# 交互式卸载/取消引用引用的程序集

F#:SRTP静态扩展方法类型匹配不一致

parameters - 是否可以将参数传递给 F# 模块?

asp.net-core - View 和静态文件的 Asp.Net Core 问题 (F#)

c# - 为什么 Microsoft F# 指南不建议从 C# 使用的代码中返回元组?

f# - 是否有库函数或运算符来创建元组?

f# - F# 语言规范中的哪个保留关键字应在 vNext 中实现?

F# ((*)2) 和 ((<<<)1) 行为不同

c# - 确定文本代码类型并转换为默认值