Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/fsharp/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
F# 基于函数调用的判别并集模式匹配_F#_Pattern Matching_Discriminated Union - Fatal编程技术网

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)