gpt4 book ai didi

f# - 无法在 F# 中重载 boolean 运算符

转载 作者:行者123 更新时间:2023-12-04 19:32:13 26 4
gpt4 key购买 nike

F# 确实允许重载像 + 这样的算术运算符,但似乎不允许重载像 || 这样的 boolean 运算符。以下代码生成一个警告和两个错误:

type MyBool =
val Value : bool
new(value) = { Value = value }
static member (||) (v1: MyBool, v2 : MyBool) =
new MyBool(v1.Value || v2.Value)
let b1 = new MyBool(true)
let b2 = new MyBool(false)
let b3 = b1 || b2

警告(关于静态成员 (||) 定义):名称“(||)”不应用作成员名称。如果定义静态成员供其他 CLI 语言使用,则改用名称“op_BooleanOr”。

错误(在“let b3”语句中的 b1 和 b2 上):此表达式应具有 bool 类型,但此处具有 MyBool 类型

如果我使用 op_BooleanOr 而不是 (||),则警告消失,但错误仍然存​​在。

当我对 MyInt 类型中的 + 运算符执行完全相同的操作时,没有警告或错误。那么,为什么当我尝试重载 || 时会出现这些警告/错误?或者&&?

最佳答案

恐怕 F# 编译器没有任何允许您覆盖它们的逻辑运算符处理方法(就像 C# 那样)。据我所知,x && y 被简单地编译为 if x then y else false,因此 x 必须是 boolean 值。我没有检查 F# 编译器是否支持在 C# 中声明的类型的这种行为,但我认为它不支持。

据我所知,为您自己的运算符模拟短路行为的最佳方法是使用 lazy 关键字来创建惰性值。然后你可以这样写:

let foo b = 
printfn "foo %b" b
MyBool(b)

lazy foo true &&! lazy foo false // Calls 'foo' for both branches
lazy foo false &&! lazy foo false // Calls 'foo' only for the first one

这两个运算符可以使用静态成员约束来定义,因此它们应该(原则上)适用于实现 C# 所需运算符的任何类型。

let inline (&&!) (x:Lazy<_>) (y:Lazy<_>) = 
if (^T: (static member op_False : ^T -> bool) x.Value)
then x.Value else x.Value &&& y.Value

let inline (||!) (x:Lazy<_>) (y:Lazy<_>) =
if (^T: (static member op_False : ^T -> bool) x.Value)
then x.Value else x.Value ||| y.Value

然后您可以使用所有必需的运算符定义您的 MyBool 类型(作为旁注,如果您这样定义它,它应该可以在 C# 中以自然的方式使用):

type MyBool(b) =
member x.Value = b
static member (|||) (v1: MyBool, v2 : MyBool) =
MyBool(v1.Value || v2.Value)
static member (&&&) (v1: MyBool, v2 : MyBool) =
MyBool(v1.Value && v2.Value)
static member op_True (v: MyBool) = v.Value
static member op_False (v: MyBool) = not v.Value

关于f# - 无法在 F# 中重载 boolean 运算符,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5002115/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com