我有一个这样的鉴别联合:
type A = |B | C of int*A
我必须像这样进行模式匹配(似乎需要括号):
match x with
| B -> printfn "B"
| C (i,a) -> printfn "%A, %A" i a
有没有一种方法来代替像这样的匹配,比如一个活动模式:
match x with
| B -> printfn "B"
| C i a -> printfn "%A, %A" i a
如果不是,为什么f#被设计成这样,与curry参数的匹配不起作用,而是强迫你使用元组?
编辑:这是受到f#列表的启发,在f#列表中,您可以使用h::t
而无需任何元组或类似的东西。源代码是这样的:
type List<'T> =
| ([]) : 'T list
| (::) : Head: 'T * Tail: 'T list -> 'T list
我想检查一下curry函数和活动模式的定义会让你更清楚这一点。
咖喱功能:一个接受多个参数的函数,但它允许你一次传递一个参数,以便返回一个功能相同但参数少一个的函数。例子:
let add a b = a + b
//val add : a:int -> b:int -> int
let add5 = add 5
//val add5 : (int -> int)
活跃模式:一种应用模式匹配的方法,其中匹配可以使用解析或其他复杂逻辑来完成。接受一个参数并返回解析的结果。输入->单个返回参数
//Example taken from https://fsharpforfunandprofit.com/posts/convenience-active-patterns/
let (|Int|_|) str =
match System.Int32.TryParse(str) with
| (true,int) -> Some(int)
| _ -> None
val ( |Int|_| ) : str:string -> int option
由于柯里化函数的全部目的是能够部分地应用该函数,因此当应用于活动模式的结果时,这个概念根本没有意义。
换句话说,活动模式的结果不能被"curry",因为你只能curry函数,而活动模式的结果是数据,而不是函数。在您的示例中,'C (i,a)'定义了活动模式情况下的返回类型,而不是函数调用。
不能在绑定模式之间使用空格作为分隔符,因为联合情况和活动模式都不支持此分隔符。语法按照f#规范:
6.9.8评价联合情况 <>之前情况(e <子> 1,…,e <子> n 子>) 子>
7.2.3活动模式(|CaseName|) arg1…参数<子> n 子>输入(|CaseName|_|) arg1…参数<子> n 子>输入
所以在并集的情况下必须有一个元组参数;香蕉函数有n+1个参数,其中n个参数是参数。只有最后一个参数绑定到模式。考虑:
type X = B | C
let (|C|) a b = C (a, b)
let i = 42
match C with
| B -> printfn "B"
| C i a -> printfn "%A, %A" i a // prints 42, (42, C)
区分联合中的C
有一个元组类型(int * A)
的值。
模式匹配的(i,a)
部分不是参数,它将i
与int
部分相匹配,将a
与A
部分相匹配。
同样可以匹配C x
, x
将保存(int * A)
的元组