受歧视工会中的咖喱争论

Curried Arguments in Discriminated Unions

我有这样一个受歧视的工会:

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# 设计成这种与 curried 参数的匹配不起作用,而是强制您使用元组?

编辑:这是受 F# 列表的启发,您可以在其中使用 h::t 而无需任何元组或类似的东西。源代码如下:

type List<'T> = 
   | ([])  :                  'T list
   | (::)  : Head: 'T * Tail: 'T list -> 'T list

您的已区分联合中的案例 C 具有元组类型 (int * A) 的值。

模式匹配的 (i,a) 部分不是参数,它是将 i 匹配到 int 部分,将 a 匹配到 A部分。

您同样可以匹配 C x,而 x 将包含 (int * A).

的元组

我认为检查柯里化函数和活动模式的定义会让您明白这一点。

柯里化函数: 一个接受多个参数但允许一次传递一个参数的函数,以便 return 一个功能相同但只接受一个较少参数的函数。示例:

let add a b = a + b
//val add : a:int -> b:int -> int
let add5 = add 5
//val add5 : (int -> int)

活动模式: 一种应用模式匹配的方法,可以使用解析或其他复杂逻辑来完成匹配。接受一个参数和 returns 解析的结果。所以输入->单return参数.

//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

由于柯里化函数的全部意义在于能够部分应用函数,因此当应用于活动模式的结果时,这个概念根本没有意义。

换句话说,活动模式的结果不能是 "curried",因为您只能柯里化函数,而活动模式的结果是不是函数的数据。在您的示例中,'C (i,a)' 正在定义活动模式案例的 return 类型,而不是函数调用。

不能将空格作为绑定模式之间的分隔符,因为联合案例和活动模式都不支持这一点。根据 F# spec 的语法:

6.9.8 评估联合案例

Case(e1,…,en)

7.2.3 活动模式

(|CaseName|) arg1 ... argn inp
(|CaseName|_|) arg1 ... argn inp

所以它必然是联合案例的一个元组参数;香蕉函数的 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)