我使用 Guid 和字符串作为数据结构中的键。在 C# 中,我花了很多(累积的)时间想知道为什么当 id 是 OrderId 并且我将其与 ContractId 相匹配时,没有事件通过我正在寻找的 id 来实现。我想要做的是防止整个类别的错误。
假设我与以下基础数据类型签订了契约(Contract):
type Contract = { Schedule : Guid; TickTable : Guid; Price : float; Quantity : float }
现在我有两个问题:
let contract =
{ Schedule = Guid.Empty; TickTable = Guid.Empty; Price = 0.; Quantity = 0. }
contract.Schedule = contract.TickTable;; // true - ugh
contract.Price = contract.Quantity;; // true - ugh
我可以解决这样的一个问题:
[<Measure>] type dollars
[<Measure>] type volume
type Contract =
{ Schedule : Guid; TickTable : Guid;
Price : float<dollars>; Quantity : float<volume> }
现在我们有:
let contract =
{ Schedule = Guid.Empty; TickTable = Guid.Empty;
Price = 0.<dollars>; Quantity = 0.<volume> }
contract.Schedule = contract.TickTable;; // true - ugh
contract.Price = contract.Quantity;; // type mismatch - yay
有没有办法可以装饰Guids,这样我就会得到类型不匹配的结果?我真的只想影响编译时间 - 理想情况下,编译的代码应该是相同的,如度量单位。
我知道我可以执行以下操作,但它看起来很难看,我希望它会导致运行时影响:
[<Measure>] type dollars
[<Measure>] type volume
type ScheduleId = ScheduleKey of Guid
type TickTableId = TickTableKey of Guid
type Contract =
{ Schedule : ScheduleId; TickTable : TickTableId;
Price : float<dollars>; Quantity : float<volume> }
let contract =
{ Schedule = ScheduleKey Guid.Empty; TickTable = TickTableKey Guid.Empty;
Price = 0.<dollars>; Quantity = 0.<volume> }
contract.Schedule = contract.TickTable;; // type error - yay
contract.Price = contract.Quantity;; // type mismatch - yay
最佳答案
您可以将任何类型包装为具有单位,即使是一般情况下,也可以通过使用 [<Measure>]
编写类型来包装任何类型。类型参数。另外,正如拉特金在评论中暗示的那样,使用 struct (which is allocated in place, not as a new object)将节省额外的分配和间接空间。
通用测量单位感知包装器:
type [<Struct>] UnitAware<'T, [<Measure>] 'u> =
val Raw : 'T
new (raw) = { Raw = raw }
let withUnit<[<Measure>] 'u> a = UnitAware<_, 'u>(a)
这样,就可以为任意类型提供一个测量单位感知值类型包装器,只需通过 withUnit<myUnit>
进行包装即可并用 .Raw
展开:
let a = 146L |> withUnit<dollars>
let b = 146L |> withUnit<volume>
a = b // Type mismatch.
由于结构比较,两个具有相同单元和相同内容的结构体包装器也将是相等的。与其他计量单位的使用一样,额外的类型安全性在运行时会丢失:box a = box b
是真的,就像 box 1.<dollars> = box 1.<volumes>
.
关于f# - 在 F# 中创建类型的不可比较版本,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27882440/