我指定了一个自定义类型,该类型需要两个浮点数并使它们成为一对(复数):
type complex = (float * float);;
let makeComplex x y = complex(x,y);;
该makeComplex
函数的类型为float -> float -> complex
,这是完全正确的。但是,我想创建一个采用复杂类型并将其设为普通对的函数。这是我尝试过的功能:
let complexToPair ((x,y):complex) = (x,y);;
但是最终的类型是float * float -> float * float
何时应该是complex -> float * float
。我是否使用了错误的语法((x,y):complex)
?
类型缩写不会隐藏或创建与其定义不同的类型。complex
并且float * float
仍然可以完全互换,您刚刚给它起了另一个名字。
在F#中创建独特类型的惯用方式是使用区分大小写的联合:
type complex = Complex of float * float
然后,您可以使用以下构造函数编写函数,以创建值和模式匹配以对其进行解构:
let makeComplex x y = Complex (x,y)
let complexToPair (Complex (x, y)) = (x, y)
您还可以使用private
以下命令从模块外部完全隐藏实现:
type complex = private Complex of float * float
消费者然后必须使用您公开的函数来创建和使用该complex
类型的值。
创建仅包含一个案例的DU是一个坏习惯(除非您打算稍后添加其他案例),因为DU的存在是为了包含和匹配已区分的数据。
@CharlesRoddie除了观点以外,您还能提供其他支持吗?有足够的证据向相反。
第一个链接不是证据而是意见。我更详细的原因是:1.命名。DU被称为“歧视联合”,因此它们用于歧视数据,一种数据不需要歧视。2.复杂性。与记录类型和记录类型不同,DU包含用于区分的支架,因此是实现此想法的更合适方法。您可以使用sharplab.io确认这一点。
您的“ contrary”链接很好,因为它非常适合使用DU来拥有一个案例,该案例可以在将来扩展更多案例,如此处讨论和我在此处的原始评论中所述。
@CharlesRoddie因此,您的论点的技术优点本质上就是只是有一种额外的
Tag
方法?考虑到通过将值包装在一个对象中而增加的大约16个字节的开销,这似乎是微不足道的,记录和单个大小写的并集都可以做到。