Ste*_*RKP 2 f# discriminated-union
我当前的 F# 中的整体类型结构和利用率运行得很好。然而,如果我做错了什么或遵循某种反模式,我想得到一些看法。我确实发现自己经常本质上期望特定逻辑中的特定类型,该类型是从更通用的类型中提取出来的,该类型是统一了一堆不同类型的可区分联合,这些类型都遵循公共处理层。
本质上我需要这个函数的特定版本:
'GeneralDiscriminatedUnionType -> 'SpecificCaseType
Run Code Online (Sandbox Code Playgroud)
我发现自己重复了许多类似以下的陈述:
let checkPromptUpdated (PromptUpdated prompt) = prompt
Run Code Online (Sandbox Code Playgroud)
这是我发现的最简单的方法;然而,其中每一个都有一个有效的编译器警告,如果使用与预期不同的类型调用函数,则可能会出现问题。这是公平的,但到目前为止我已经有大约 40 到 50 个这样的了。
所以我开始尝试以下方法,这实际上更好,因为它会引发错误使用的有效异常(两者是相同的):
let checkPromptUpdated input = match input with | PromptUpdated prompt -> prompt | _ -> invalidOp "Expecting Prompt"
let checkPromptUpdated = function | PromptUpdated prompt -> prompt | _ -> invalidOp "Expecting Prompt"
Run Code Online (Sandbox Code Playgroud)
然而,这看起来更混乱,我试图在我重新处理这些混乱之前找出是否有人有任何建议。
有没有某种方法可以将这种更广泛的逻辑应用到更通用的函数中,然后让我能够以更干净、更直接和可读的方式编写这个 50 到 100x 的代码?
这个问题只是尝试编写更清晰的代码的问题。
这是一个 DU 的示例,我正在尝试编写函数以便能够从案例中提取特定类型的值:
type StateEvent =
| PromptUpdated of Prompt
| CorrectAnswerUpdated of CorrectAnswer
| DifficultyUpdated of Difficulty
| TagsUpdated of Tag list
| NotesUpdated of Notes
| AuthorUpdated of Author
Run Code Online (Sandbox Code Playgroud)
如果该checkPromptUpdated函数仅适用于这种情况的事件PromptUpdated,那么我认为最好的设计是该函数应该仅采用 type 的值Prompt(而不是 type 的值StateEvent)作为参数:
let checkPromptUpdated prompt =
// do whatever checks you need using 'prompt'
Run Code Online (Sandbox Code Playgroud)
当然,这意味着模式匹配将从该函数移动到调用它的函数,或者进一步移动到您实际接收StateEvent并需要处理所有其他情况的地方。但这正是您想要的 - 一旦您对事件进行模式匹配,您就可以使用更具体的类型,例如Prompt.