2016-04-08 37 views
5

以下的观察(那种惊讶我的)一个小例子:局部解构(F#)

type Vector = V of float*float 

// complete unfolding of type is OK 
let projX (V (a,_)) = a 

// also works 
let projX' x = 
    match x with 
    | V (a, _) -> a 

// BUT: 
// partial unfolding is not Ok 
let projX'' (V x) = fst x 

// consequently also doesn't work 
let projX''' x = 
    match x with 
    | V y -> fst y 

是什么使得它不可能去匹配部分解构型的原因是什么?

一些局部的解构,似乎是好:

// Works 
let f (x,y) = fst y 

编辑: 好吧,我现在明白所描述的行为的“技术”原因(谢谢您的回答&评论)。然而,我认为语言明智,与其他语言相比,这种行为感觉有点“不自然”:

“代数”,对我来说,区分类型“t”与类型“(t )”。括号(在这种情况下)用于给予优先权,例如,在“(t * s)* r”与“t *(s * r)”中。此外FSI的答案。因此,无论是我送

type Vector = (int * int) 

type Vector = int * int 

到FSI,答案永远是

型矢量= INT * INT

鉴于这些观察,得出的结论是“int * int”和“(int * int)”表示完全相同的类型和t在任何一段代码中的所有事件都可以用另一段代替(参考文献1)。透明度)......正如我们所看到的,这不是真的。

此外,为了解释手边的行为,我们不得不求助于谈论“编译后的代码如何”,而不是语言的语义属性,而这些语义属性表示存在一些“语言语义之间的紧张关系和编译器实际做的事情。

+1

试着用'type Vector = V(float * float)'来代替编译器为内容使用一个实际的元组。 – kvb

+0

它的工作原理! ...但它怎么会有所作为...我的意思是 类型Vector =(浮点数V)* float甚至不会有效? –

+1

问题是:x * y'的V是否意味着“V拥有x和y类型的元组的元组”或者“V拥有x和y两个不同的字段”?如果你不加括号,那么编译器会假设后者,但是如果你用括号括起来,它意味着前者。这种区别主要与其他.NET语言的互操作性有关,但正如您发现的,它也会影响在某些情况下如何与F#中的此类类型的值进行交互。 – kvb

回答

1

在F#

type Vector = V of float*float 

只是一个退化联盟(你可以看到,在Visual Studio中徘徊的话),所以它等同于:

type Vector = 
    | V of float*float 

of之后的部分创建两个anonymous field s(如F#参考中所述)和一个接受float类型两个参数的构造函数。

如果定义

type Vector2 = 
    | V2 of (float*float) 

,只有一个匿名场是浮动的元组和一个单参数的构造函数。正如在评论中指出的那样,您可以使用Vector2进行所需的模式匹配。

了这一切之后,它可能看起来不合逻辑的是下面的代码工作:

let argsTuple = (1., 1.) 
let v1 = V argsTuple 

但是,如果考虑到有一个隐藏的模式匹配,一切都应该是清楚的。

编辑:

F# language spec (p 122)明确指出,括号此事联合定义:

圆括号的联合定义,显著。因此,下面的两个定义不同:

type CType = C of int * int

type CType = C of (int * int)

在第一实施例中的缺乏括号表示该联合的情况下有两个参数。第二个例子中的圆括号 指示union工程案例采用一个参数,该参数是第一类元组值。

我认为这样的行为是事实,你可以在联盟的定义,定义更加复杂的图案,如一致:

type Move = 
     | M of (int * int) * (int * int) 

能够使用联盟与多个参数也进行了大规模的感觉,特别是在互操作的情况下,使用元组时很麻烦。

您所使用的另一件事:

type Vector = int * int 

type abbreviation它只是给出了一个名称某种类型。围绕int * int放置括号并没有什么不同,因为这些括号会被视为分组括号。

+0

我(理解并)同意你所说的一切,我会接受这个答案。不过,我仍然认为设计明智的是,联合定义中括号的作用更多的是务实而不是清洁/优雅的一面;)。可以有联合定义,其中一些括号用于分组,而另一些则如前所讨论的那样...形式“... = Y的形式”的进一步定义不仅取决于Y“作为类型”... –

+0

我同意它不是语法上最直观,最干净的设计选择;另一方面它也很丑陋。 –