“拆箱”受歧视工会的多功能类型/寻找好的解决方法

发布于 2024-12-12 21:06:55 字数 1081 浏览 0 评论 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 42 和 Real 13.)运行计算,但能够返回适当的包装器。如果我想添加 Real 1.Real 1.5 我想提取 1.0 + 1.5 = 2.5 然后继续使用 Real 2.5,但是我不想将所有内容都作为浮点数处理,这样我就可以区分整数和浮点数。

For a small AST parser i have a small discriminated union

type Numerical =
    | Int of int
    | Real of float

for the use in some other constructs like

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

When i have a method like this

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

I know that F# infers the int type and produces an error with the Real pattern in the second line, so I want to know, which code-design would be the best one to be able to handle such "generic" types and return their appropriate values with the given types.

EDIT

I have here an either or situation which leads to functions like

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"

however i would like a method which encapsulates both cases and "automatically chooses the correct one".

This whole effort should lead to the possibility to be able to really run computations with the "boxed" values like Int 42 and Real 13. with primitive data types but to able to return the appropriate wrapper. If i want to add Real 1. and Real 1.5 I want to extract 1.0 + 1.5 = 2.5 and then go on with Real 2.5, however I do not want to handle everything as floats so that I have the distinction between ints and floats.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

时常饿 2024-12-19 21:07:03
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
let eval<'T> (e:Numerical):'T =
    match e with
    | Int n -> n :> obj :?> 'T
    | Real r -> r :> obj :?> 'T

DEMO

> 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
心病无药医 2024-12-19 21:07:02

您可以将结果转换为 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"

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

You could cast the results to obj:

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

But that's probably not what you want.

Another option would be implement your own operations on 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"

You can't have a function that has different compile-time return type based on some run-time value.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文