简体   繁体   English

F# - 从有区别的联合中提取/解包预期案例的类型值的最简洁方法?

[英]F# - Cleanest way to Extract/Unwrap an Expected Case's Typed Value from Discriminated Union?

The overall type structure and utilization in my current F# is working very well.我当前的 F# 中的整体类型结构和利用率运行良好。 However, I want to get some perspective if I am doing something incorrectly or following some kind of anti-pattern.但是,如果我做错了什么或遵循某种反模式,我想获得一些观点。 I do find myself very often essentially expecting a particular type in particular logic that is pulling from a more general type that is a Discriminated Union unifying a bunch of distinct types that all follow layers of common processing.我确实发现自己经常从本质上期待一种特定类型的特定逻辑,该特定类型是从一个更通用的类型中提取出来的,该类型是一个可区分的联合,它统一了一堆不同的类型,这些类型都遵循公共处理层。

Essentially I need particular versions of this function:基本上我需要这个 function 的特定版本:

'GeneralDiscriminatedUnionType -> 'SpecificCaseType

I find myself repeating many statements like the following:我发现自己重复了许多类似以下的陈述:

let checkPromptUpdated (PromptUpdated prompt) = prompt

This is the simplest way that I've found to this;这是我发现的最简单的方法; however, every one of these has a valid compiler warning that makes sense that there could be a problem if the function is called with a different type than the expected.然而,每一个都有一个有效的编译器警告,如果 function 被调用的类型与预期的不同,则可能会出现问题。 This is fair, but I so far have like 40 to 50 of these.这是公平的,但到目前为止我有 40 到 50 个。

So I started trying the following out, which is actually better, because it would raise a valid exception with incorrect usage (both are the same):所以我开始尝试以下方法,这实际上更好,因为它会引发一个使用不正确的有效异常(两者都是相同的):

let checkPromptUpdated input  = match input with | PromptUpdated prompt -> prompt | _ -> invalidOp "Expecting Prompt"    
let checkPromptUpdated = function | PromptUpdated prompt -> prompt | _ -> invalidOp "Expecting Prompt"

However, this looks a lot messier and I'm trying to find out if anyone has any suggestions prior to me doing this messiness all over.但是,这看起来更混乱,我试图找出是否有人在我做这种混乱之前有任何建议。

Is there some way to apply this wider logic to a more general function that could then allow me to write this 50 to 100x in a cleaner and more direct and readable way?有什么方法可以将这种更广泛的逻辑应用到更通用的 function 上,然后可以让我以更清晰、更直接和可读的方式编写 50 到 100 倍的代码?

This question is just a matter of trying to write cleaner code.这个问题只是尝试编写更清晰的代码的问题。

This is an example of a DU that I'm trying to write functions for to be able to pull the particular typed values from the cases:这是一个 DU 示例,我正在尝试编写函数以便能够从案例中提取特定类型的值:

type StateEvent = 
| PromptUpdated of Prompt
| CorrectAnswerUpdated of CorrectAnswer
| DifficultyUpdated of Difficulty
| TagsUpdated of Tag list
| NotesUpdated of Notes
| AuthorUpdated of Author

If the checkPromptUpdated function only works on events that are of the PromptUpdated case, then I think the best design is that the function should be taking just a value of type Prompt (instead of a value of type StateEvent ) as an argument:如果checkPromptUpdated function 仅适用于PromptUpdated情况下的事件,那么我认为最好的设计是 function 应该只采用Prompt类型的值(而不是StateEvent类型的值)作为参数:

let checkPromptUpdated prompt = 
  // do whatever checks you need using 'prompt'

Of course, this means that the pattern matching will get moved from this function to a function that calls it - or further - to a place where you actually receive StateEvent and need to handle all the other cases too.当然,这意味着模式匹配将从这个 function 移动到调用它的 function - 或者进一步 - 到您实际接收StateEvent并且也需要处理所有其他情况的地方。 But that is exactly what you want - once you pattern match on the event, you can work with the more specific types like Prompt .但这正是您想要的——一旦您对事件进行模式匹配,您就可以使用更具体的类型,例如Prompt

This works for me这对我有用

let (TypeUWantToExtractFrom unwrappedValue) = wrappedValue

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM