我想知道是否有一种很好的方式将DU案例的内容暴露给DU类型本身。
例如:
befall_fallen-fell
Line - Eddying, dizzying, closing-round
Line - With soft and drunken laughter-laugh_laugh
laughter-laugh_laugh
Line - Veiling all that may befall_fallen-fell
重新审视我的设计后,就像Fyodor指出的那样,我决定为IShape创建一个界面。
[<Measure>] type inch
module StructuralShape =
type Plate =
{
Length : float<inch>
Thickness : float<inch>
}
type SingleAngle =
{
VerticalLeg : float<inch>
HorizontalLeg : float<inch>
Thickness : float<inch>
}
type StructuralShape =
| Plate of Plate
| SingleAngle of SingleAngle
let area (ss : StructuralShape) =
match ss with
| Plate pl -> pl.Length * pl.Thickness
| SingleAngle sa ->
(sa.HorizontalLeg + sa.VerticalLeg - sa.Thickness) * sa.Thickness
type StructuralShape with
member ss.Area = area ss
module Test =
open StructuralShape
let myShape = Plate {Length = 2.0<inch>; Thickness = 0.25<inch>}
let area = myShape.Area
// Looking to allow the user of the library
// to access the internal shape properties
// without having to use some type of 'get shape' function
let length = myShape.Length // fails
注意:为简单起见,这是库的简化版本。
答案 0 :(得分:4)
目前还不清楚你想在这里实现什么目标。我怀疑你的设计中可能存在不一致的设计而没有意识到它。
如果您的StructuralShape
类型只有一个案例,那么为什么还需要它?只需使用Plate
代替!
如果您的StructuralShape
类型会有更多案例,那么当实际值没有Thickness
字段时会发生什么?
如果您的StructuralShape
类型包含更多案例,但所有案例都必须包含Thickness
字段,并且该字段具有相同类型且含义相同对于他们所有人来说,更好的设计就是“提升”。公共类型的公共字段,只留下DU下的差异:
type Plate = { Length: float }
type Foo = { Bar: string }
type StructuralShapeInfo = Plate of Plate | Foo of Foo
type StructuralShape = { Info: StructuralShapeInfo; Thickness: float }
(原谅我选择的Info
后缀;我意识到这不是最好的选择,但我不能在不了解您的域名的情况下想出一个更好的选择虽然;编程中存在三个难题:命名内容和逐个错误)
答案 1 :(得分:2)
您可以增加与成员的歧视联盟,这对于在以下情况下方便访问很有用:
type StructuralShape =
| Plate of Plate
member this.Thickness = match this with Plate p -> p.Thickness
如果您向StructuralShape
添加任何新案例,则需要在此属性的代码中处理该案例。
这可能是一个有用的事情,但是Fyodor在他关于重组数据模型的答案中提出了一个非常好的观点,因此这是不必要的。