2

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

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
4

3 回答 3

3

我认为检查柯里化函数和活动模式的定义将使您清楚这一点。

Curried 函数:一个接受多个参数但允许您一次将它们传入一个函数以返回一个执行相同操作但接受更少参数的函数的函数。例子:

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

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

换句话说,活动模式的结果不能“柯里化”,因为您只能对函数进行柯里化,而活动模式的结果是不是函数的数据。在您的示例中,“C (i,a)”定义了活动模式案例的返回类型,而不是函数调用。

于 2016-08-26T15:51:35.210 回答
2

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

您的模式匹配的(i,a)部分不是参数,它匹配iint部分和a部分A

您可以同样匹配C xx持有(int * A).

于 2016-08-26T15:25:43.880 回答
2

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

6.9.8 评估联合案例

案例(e 1 ,…,e n

7.2.3 活动模式

(|CaseName|) arg 1 ... arg n inp
(|CaseName|_|) arg 1 ... arg n 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)
于 2016-08-26T20:08:52.920 回答