F# 基于函数调用的判别并集模式匹配
我的问题是受这个启发的: 下面是一个代码:F# 基于函数调用的判别并集模式匹配,f#,pattern-matching,discriminated-union,F#,Pattern Matching,Discriminated Union,我的问题是受这个启发的: 下面是一个代码: type A = | X of int * int | Y of string let f (A.X(a, b)) = a + b 它可以工作,但有一个警告: 有道理;我没有你的对手 但是如果我加上一行 let f (A.Y(s)) = 10 然后我得到一个错误: 有没有一个很好的方法来修复它,并且仍然在函数参数中使用模式匹配?如果没有,那么为什么他们会创建这样奇怪的语法,总是导致警
type A =
| X of int * int
| Y of string
let f (A.X(a, b)) = a + b
它可以工作,但有一个警告:
有道理;我没有你的对手
但是如果我加上一行
let f (A.Y(s)) = 10
然后我得到一个错误:
有没有一个很好的方法来修复它,并且仍然在函数参数中使用模式匹配?如果没有,那么为什么他们会创建这样奇怪的语法,总是导致警告?您需要在参数上进行模式匹配:
let f = function
| X(a, b) -> a + b
| Y(_) -> 10
当你定义
let f (A.X(a, b)) = a + b
f
具有类型A->int
,而不是A.X->int
。它不是为A.Y
的实例值定义的,因此会出现不完全匹配警告
您的f
的第二个定义也有类型A->int
,因此是第一个定义的重复,因此是错误的。如果您想在某个联合类型上编写一个total函数,您应该使用模式匹配function
或match
编辑:对于注释,如果您有多个参数要同时匹配,则可以使用match
,例如:
let f a1 a2 =
match (a1, a2) with
| (X(a, b), X(a', b')) -> a + b
| (X(a, b), Y(s)) -> a + 10
| (Y(s), X(a, b)) -> 10
| (Y(s), Y(s')) -> 20
某些模式匹配可能是完整的,并且在函数参数中可能有用,例如,
fst
的此定义是模式匹配一个元组,并且对所有2个元组都是完整的
let fst (a,_) = a
其他一些例子:
type Container = Container of string
let unwrap (Container(v)) = v
type Person = { Name:string; Age:int }
let getName {Name=name} = name
正如其他答案所说,最好的方法似乎是使用
函数
或匹配
关键字的模式匹配。然而,F#的本机模式匹配本身就非常强大。考虑下面的代码,<强>但是我并不提倡在真实世界的项目中使用它。< /强>我更愿意使用它作为一种练习来更好地理解语言。
let f ((A.X(a, b), _ ) | (A.Y(_), (a, b))) = a + b
// usage
let x1 = f(A.X(10, 42), (100, 1)) // x1 = 52
let x2 = f(A.Y("foo"), (100, 1)) // x2 = 101
这是怎么回事
- 函数体计算元组中两个值的总和李>
- 元组可以从
中提取,也可以作为单独的参数提供李>A.X
- 该函数接受一个额外的参数,该参数可被视为回退值。也就是说,当第一个参数是
时,我们仍然需要求和A.Y(string)
- 如果第一个参数的某个意义值为
,则将忽略回退值A.X(int,int)
进一步阅读:。+1关于函数定义中记录的模式匹配的一个非常有趣的例子,函数定义通常采用括号模式
(pat)
,但是对于列表、数组或记录模式,参数是可选的。确实,参数已删除。感谢您的回复。你的建议很好,但似乎不能解决一般问题。假设我们有两个有区别的并集和一个具有两个模式匹配参数的函数。在这种情况下,我想,function
关键字没有帮助哇,这是一个非常有趣的参数模式匹配示例。您也可以将析取模式与常量或空测试模式一起使用,例如空合并操作符let(|?)ab=(fun(null,x | x,|)->x)(a,b)