F# - 字符串 |联合推理

F# - string | int inference on union

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

我有一个类型

type StringOrInt = 
 | String of string
 | Int of int

然后是函数

let returnSelf (x: StringOrInt) = x

目前必须像

那样调用函数
returnSelf (String "hello")

是否可以

returnSelf "hello"

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

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

给出一个示例函数:

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

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

(* % is a unary prefix operator *)
call %"abc" 
call %1

我们需要提供一些方法来告诉如何将普通 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

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

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

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