0

对于一个小的 AST 解析器,我有一个小的有区别的联合

type Numerical =
    | Int of int
    | Real of float

用于其他一些结构,如

type Vector = Numerical list
Vector [Int 42; Real 13.5]

当我有这样的方法时

let eval (e:Numerical) =
    match e with
    | Int n -> ... (* return int *)
    | Real r -> ... (* return float *)

我知道 F# 推断int类型并在第二行中使用模式产生错误Real,所以我想知道,哪种代码设计是能够处理此类“通用”类型并返回其适当值的最佳设计给定的类型。

编辑

我在这里有一个非此即彼的情况,导致类似的功能

let getInt = function
| Int n -> n
| Real _ -> failwith "Given value doesn't represent an int"

let getReal = function
| Real n -> n
| Int _ -> failwith "Given value doesn't represent a real number"

但是我想要一种封装这两种情况并“自动选择正确的情况”的方法。

这整个努力应该导致能够真正使用“盒装”值(如原始数据类型)运行计算,Int 42Real 13.能够返回适当的包装器。如果我想添加Real 1.并且Real 1.5我想提取1.0 + 1.5 = 2.5然后继续Real 2.5,但是我不想将所有内容都作为浮点数处理,以便区分整数和浮点数。

4

2 回答 2

3

您可以将结果转换为obj

let eval (e:Numerical) =
    match e with
    | Int n -> n :> obj
    | Real r -> r :> obj

但这可能不是你想要的。

另一种选择是在以下位置实施您自己的操作Numerical

let (+) a b =
    match (a,b) with
    | (Int an, Int bn) -> Int (an + bn)
    | (Real ar, Real br) -> Real (ar + br)
    | _ -> failwith "Can't add Int and Real"

您不能拥有基于某些运行时值具有不同编译时返回类型的函数。

于 2011-10-30T16:50:15.797 回答
0
let eval<'T> (e:Numerical):'T =
    match e with
    | Int n -> n :> obj :?> 'T
    | Real r -> r :> obj :?> 'T

演示

> eval<float>(Real 4.5);;
val it : float = 4.5
> eval<int>(Int 42);;
val it : int = 42
> let x:float = eval (Real 5.5);;
val x : float = 5.5
> let x:int = eval (Real 5.5);;//NG typemismatch
于 2011-10-30T21:57:25.207 回答