代码之家  ›  专栏  ›  技术社区  ›  Thomas

使类型别名在F中不可互换#

f#
  •  1
  • Thomas  · 技术社区  · 3 年前

    下面是一个例子:

    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
    

    不应编译,因为它会传递时间跨度

    但话说回来:

    let b' = x b
    

    正在传递类型T,应该编译。

    有什么简单而优雅的方法可以做到这一点吗?这样做的目的是能够使用TimeSpan,但将选项限制为某些特定值。

    现在我正在使用一个需要转换为TimeSpan的枚举,然后TimeSpan重新转换为枚举(如果它们存在于枚举中)。太难看了。

    1 回复  |  直到 3 年前
        1
  •  0
  •   Brian Berns    3 年前

    我想制作一个与TimeSpan相同但不是TimeSpan的类型。我希望能够在彼此之间进行转换,但在函数签名方面不能等同。

    这在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 ".