【发布时间】:2016-04-08 18:49:54
【问题描述】:
跟随一个观察的最小例子(这让我很惊讶):
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
编辑: 好的,我现在了解所描述行为的“技术”原因(感谢您的回答和 cmets)。但是,我认为语言方面,与其他语言相比,这种行为感觉有点“不自然”:
“代数”,对我来说,区分类型“t”和类型“(t)”似乎很奇怪。括号(在这种情况下)用于给出优先级,例如在“(t * s)* r”与“t *(s * r)”中。 fsi 也会相应地回答,我是否发送
type Vector = (int * int)
或
type Vector = int * int
对于 fsi,答案总是
类型向量 = int * int
鉴于这些观察,可以得出结论,“int * int”和“(int * int)”表示完全相同的类型,因此在任何一段代码中出现的所有一个都可以用另一个替换(参考透明度)...正如我们所见,这是不正确的。
更重要的是,为了解释手头的行为,我们不得不诉诸“一些代码在编译后的样子”而不是语言的语义属性,因为 imo 表明存在一些“紧张” " 在语言语义和编译器实际执行的操作之间。
【问题讨论】:
-
尝试使用
type Vector = V of (float*float)来让编译器对内容使用实际的元组。 -
它有效! ...但它怎么能有所作为...我的意思是类型 Vector = (V of float)*float 甚至无效?
-
问题是:
V of x*y的意思是“V 拥有 x 和 y 类型的项的元组”还是“V 拥有 x 和 y 类型的两个不同字段”?如果你不给元组加上括号,那么编译器会假定后者,但如果你给它加上括号,那就意味着前者。这种区别主要对与其他 .NET 语言的互操作很重要,但正如您发现的那样,在某些情况下,它也会影响您在 F# 中与此类类型的值进行交互的方式。 -
感谢您的评论,请参阅我的编辑。
标签: constructor f# pattern-matching