使类型别名在 F# 中不可互换
making type aliases non interchangeable in F#
这是一个例子:
type T =
TimeSpan
let x (y: T) =
printfn $"{y}"
let a:TimeSpan = TimeSpan.FromSeconds(3)
let b:T = TimeSpan.FromSeconds(3)
let a' = x a
let b' = x b
在这种情况下,我想创建一个与 TimeSpan 相同但不是 TimeSpan 的类型。我希望能够相互转换,但在函数签名方面并不等同。
例如,x 函数采用类型 T,所以行:
let a' = x a
不应编译,因为它传递了 TimeSpan
但是行:
let b' = x b
正在传递类型 T 并且应该编译。
是否有一些简单而优雅的方法可以实现这一点?这样做的目标是能够使用 TimeSpan,但将选项限制为某些特定值。
现在我正在使用需要转换为 TimeSpan 的枚举,然后如果 TimeSpans 存在于枚举中,则将其重新转换为枚举。比较丑
I want to make a type which is identical to TimeSpan but is NOT TimeSpan. I would like the ability to cast between one another, but not be equivalent when it comes to function signatures.
这在 F# 中是不可能的,但完成类似事情的通常方法是使用 single-case unions,例如:
type T = T of TimeSpan
let x (T y) =
printfn "%A" y // y is the inner TimeSpan value
let a:TimeSpan = TimeSpan.FromSeconds(3.0)
let b:T = TimeSpan.FromSeconds(3.0) |> T
let a' = x a // doesn't compile
let b' = x b
我认为您在这里处理的一般问题称为“primitive obsession”。
您可以使用单格 DU,也可以使用计量单位来执行此操作。 UMX 特别支持时间跨度。
这是一个例子:
type T =
TimeSpan
let x (y: T) =
printfn $"{y}"
let a:TimeSpan = TimeSpan.FromSeconds(3)
let b:T = TimeSpan.FromSeconds(3)
let a' = x a
let b' = x b
在这种情况下,我想创建一个与 TimeSpan 相同但不是 TimeSpan 的类型。我希望能够相互转换,但在函数签名方面并不等同。
例如,x 函数采用类型 T,所以行:
let a' = x a
不应编译,因为它传递了 TimeSpan
但是行:
let b' = x b
正在传递类型 T 并且应该编译。
是否有一些简单而优雅的方法可以实现这一点?这样做的目标是能够使用 TimeSpan,但将选项限制为某些特定值。
现在我正在使用需要转换为 TimeSpan 的枚举,然后如果 TimeSpans 存在于枚举中,则将其重新转换为枚举。比较丑
I want to make a type which is identical to TimeSpan but is NOT TimeSpan. I would like the ability to cast between one another, but not be equivalent when it comes to function signatures.
这在 F# 中是不可能的,但完成类似事情的通常方法是使用 single-case unions,例如:
type T = T of TimeSpan
let x (T y) =
printfn "%A" y // y is the inner TimeSpan value
let a:TimeSpan = TimeSpan.FromSeconds(3.0)
let b:T = TimeSpan.FromSeconds(3.0) |> T
let a' = x a // doesn't compile
let b' = x b
我认为您在这里处理的一般问题称为“primitive obsession”。
您可以使用单格 DU,也可以使用计量单位来执行此操作。 UMX 特别支持时间跨度。