针对字符串的模式匹配 属性
Pattern matching against a string property
我正在反序列化来自 JSON 的一些映射,稍后我需要基于反序列化类型的 string
字段进行模式匹配,如下所示:
let mappings = getWorkItemMappings
let result =
workItemMappings
|> Seq.find (fun (m: WorkItemMapping) -> m.Uuid = workTime.workItemUuid)
match mapping.Name with
即使我完成所有情况的模式匹配,我仍然得到 Incomplete pattern matches on this expression.
。由于 Name
字段的字符串类型,这对我来说很明显。
有没有办法告诉编译器 Name
字段的哪些值可用?
我想我可以为可能的映射类型创建一个联合类型,并尝试将 JSON 反序列化为这个联合类型,但如果还有其他选择,我想这样做。
很难理解你在问什么。也许这个片段可以提供帮助。它演示了如何在模式匹配中使用文字字符串常量,以及如何在函数中重用。这在添加和删除案例时增加了一些安全性和可读性。如果您不希望直接序列化 DU,那么这作为解决方案的一部分可能很有用。
type MyDu =
| A
| B
| C
let [<Literal>] A' = "A"
let [<Literal>] B' = "B"
let [<Literal>] C' = "C"
let strToMyDuOption (s: string) =
match s with
| A' -> Some A
| B' -> Some B
| C'-> Some C
| _ -> None
let strToMyDu (s: string) =
match s with
| A' -> A
| B' -> B
| C'-> C
| s -> failwith $"MyDu case {s} is unknown."
let myDuToStr (x: MyDu) =
match x with
| A -> A'
| B -> B'
| C -> C'
// LINQPad
let dump x = x.Dump()
strToMyDuOption A' |> dump
strToMyDuOption "x" |> dump
myDuToStr A |> dump
如果您在字符串值上进行模式匹配,编译器无法静态保证它只会有特定值,因为构造不同值的字符串总是可能的。它来自 JSON 的事实并没有帮助 - 你可能总是有一个无效的 JSON.
最好的选择是添加一个引发自定义描述性异常的默认案例。您在其他地方处理的任何一个(表明 JSON 文件无效)或(如果您在其他地方检查有效性)像这样:
let parseFood f =
match f with
| "burger" -> 1
| "pizza" -> 2
| _ -> raise(invalidArg "f" $"Expected burger or pizza but got {f}")
请注意,F# 编译器非常 谨慎。它甚至不允许您使用模式匹配来处理枚举值,因为在幕后,有一些方法可以创建无效的枚举值!例如:
type Foo =
| A = 1
let f (a:Foo) =
match a with
| Foo.A -> 0
warning FS0104: Enums may take values outside known cases. For example, the value 'enum (0)' may indicate a case not covered by the pattern(s).
我正在反序列化来自 JSON 的一些映射,稍后我需要基于反序列化类型的 string
字段进行模式匹配,如下所示:
let mappings = getWorkItemMappings
let result =
workItemMappings
|> Seq.find (fun (m: WorkItemMapping) -> m.Uuid = workTime.workItemUuid)
match mapping.Name with
即使我完成所有情况的模式匹配,我仍然得到 Incomplete pattern matches on this expression.
。由于 Name
字段的字符串类型,这对我来说很明显。
有没有办法告诉编译器 Name
字段的哪些值可用?
我想我可以为可能的映射类型创建一个联合类型,并尝试将 JSON 反序列化为这个联合类型,但如果还有其他选择,我想这样做。
很难理解你在问什么。也许这个片段可以提供帮助。它演示了如何在模式匹配中使用文字字符串常量,以及如何在函数中重用。这在添加和删除案例时增加了一些安全性和可读性。如果您不希望直接序列化 DU,那么这作为解决方案的一部分可能很有用。
type MyDu =
| A
| B
| C
let [<Literal>] A' = "A"
let [<Literal>] B' = "B"
let [<Literal>] C' = "C"
let strToMyDuOption (s: string) =
match s with
| A' -> Some A
| B' -> Some B
| C'-> Some C
| _ -> None
let strToMyDu (s: string) =
match s with
| A' -> A
| B' -> B
| C'-> C
| s -> failwith $"MyDu case {s} is unknown."
let myDuToStr (x: MyDu) =
match x with
| A -> A'
| B -> B'
| C -> C'
// LINQPad
let dump x = x.Dump()
strToMyDuOption A' |> dump
strToMyDuOption "x" |> dump
myDuToStr A |> dump
如果您在字符串值上进行模式匹配,编译器无法静态保证它只会有特定值,因为构造不同值的字符串总是可能的。它来自 JSON 的事实并没有帮助 - 你可能总是有一个无效的 JSON.
最好的选择是添加一个引发自定义描述性异常的默认案例。您在其他地方处理的任何一个(表明 JSON 文件无效)或(如果您在其他地方检查有效性)像这样:
let parseFood f =
match f with
| "burger" -> 1
| "pizza" -> 2
| _ -> raise(invalidArg "f" $"Expected burger or pizza but got {f}")
请注意,F# 编译器非常 谨慎。它甚至不允许您使用模式匹配来处理枚举值,因为在幕后,有一些方法可以创建无效的枚举值!例如:
type Foo =
| A = 1
let f (a:Foo) =
match a with
| Foo.A -> 0
warning FS0104: Enums may take values outside known cases. For example, the value 'enum (0)' may indicate a case not covered by the pattern(s).