F# - 字符串 | 联合的 int 推断

Jos*_*osh 3 f#

我很确定这是不可能的,但我想我会仔细检查一下。我想我正在尝试模仿打字稿的联合类型。

我有一个类型

type StringOrInt = 
 | String of string
 | Int of int
Run Code Online (Sandbox Code Playgroud)

然后是一个函数

let returnSelf (x: StringOrInt) = x
Run Code Online (Sandbox Code Playgroud)

目前该函数必须像这样调用

returnSelf (String "hello")
Run Code Online (Sandbox Code Playgroud)

是否可以做

returnSelf "hello"
Run Code Online (Sandbox Code Playgroud)

并推断它是一个有效的 StringOrInt?

Bar*_*ski 6

目前还不支持开箱即用,但可以实现相当简单的通用转换方法。

给出一个示例函数:

let call v = (* v has inferred type StringOrInt *)
    match v with
    | String s -> printfn "called a string %s" s
    | Int i -> printfn "called an int %i" i
Run Code Online (Sandbox Code Playgroud)

我们最终可以这样称呼它:

(* % is a unary prefix operator *)
call %"abc" 
call %1
Run Code Online (Sandbox Code Playgroud)

我们需要提供一些方法来告诉如何将普通的 string/int 转换为StringOrInt类型。这可以通过示例约定调用来使用:

type StringOrInt =
    | String of string
    | Int of int
    static member inline From(i: int) = Int i
    static member inline From(s: string) = String s
Run Code Online (Sandbox Code Playgroud)

这里我们的可区分联合提供了两个负责强制转换的静态方法。由于它们对应于相同的命名约定,因此我们可以将它们与 F# 静态解析的泛型类型参数一起使用 - 这些泛型在编译时解析,不像 .NET 泛型也存在于运行时 - 来创建转换函数(或运算符) ):

(* casting operator *)
let inline (~%) (x: ^A) : ^B =
    (^B : (static member From: ^A -> ^B) x)
Run Code Online (Sandbox Code Playgroud)

这样,您就可以%在任何以静态From方法形式实现转换机制的类型上使用前缀运算符。