F# 在受歧视的工会中讨好争论

F# 在受歧视的工会中讨好争论,f#,discriminated-union,active-pattern,F#,Discriminated Union,Active Pattern,我有这样一个受歧视的联盟: type A = |B | C of int*A 我必须像这样进行模式匹配(括号似乎是必需的): 是否有一种方法可以将这样的内容与活动模式匹配: match x with | B -> printfn "B" | C i a -> printfn "%A, %A" i a 如果不是的话,为什么F#被设计成这样,与curry参数的匹配不起作用,反而迫使您使用元组 编辑:这是受F#list的启发,在F#list中,您可以使用h::t,而无需任何元组或类似的

我有这样一个受歧视的联盟:

type A = |B | C of int*A
我必须像这样进行模式匹配(括号似乎是必需的):

是否有一种方法可以将这样的内容与活动模式匹配:

match x with
| B -> printfn "B"
| C i a -> printfn "%A, %A" i a
如果不是的话,为什么F#被设计成这样,与curry参数的匹配不起作用,反而迫使您使用元组

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

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

您的受歧视的并集中的大小写
C
的值为元组类型
(int*a)

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


您可以与
cx
匹配,并且
x
将包含
(int*a)

的元组。我认为,检查当前函数和活动模式的定义会让您明白这一点

咖喱功能: 一种函数,它接受多个参数,但允许您一次传入一个参数,以便返回一个执行相同操作但只接受较少一个参数的函数。例如:

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”,因为您只能curry函数,而活动模式的结果是不是函数的数据。在您的示例中,“C(i,a)”定义的是活动模式大小写的返回类型,而不是函数调用。

不能将空格作为绑定模式之间的分隔符,因为联合大小写和活动模式都不支持这一点。语法如下所示:

6.9.8评估联合案例
我不完全确定当涉及到一个活动模式时,你所说的“咖喱争论”是什么意思。curry参数表示可以部分应用函数。这对一个活动模式意味着什么?@mydogisbox我说咖喱是因为像
let(| Test |)abc=a+b+c
这样的活动模式有一个
val(| Test |)的签名:a:int->b:int->c:int->int
No,没有办法。F#不是Haskell。我的问题是,如果没有元组语法,我为什么不能创建值
I
a
?也许有一种方法可以改变受歧视的工会的签名?这是一个很好的答案,但对curry函数进行模式匹配并不是“没有意义”;您可以在Haskell中实现。@MarkSeemann我特别指出,活动模式(通常不是模式匹配)返回一段数据,这与将数据传递到函数中的currying不同。也许我在这一点上错了?
//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
Case(e1,…,en) (|CaseName|) arg1 ... argn inp (|CaseName|_|) arg1 ... argn inp
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)