F# 运算符重载:(+) 用于用户定义类型
以下代码在“评估”中失败:
“该表达式预计具有 Complex 类型,但这里具有 double list 类型”
我是否违反了“(+)”上运算符重载的一些规则?
如果我将“(+)”更改为“添加”,则一切正常。
open Microsoft.FSharp.Math
/// real power series [kn; ...; k0] => kn*S^n + ... + k0*S^0
type Powers = double List
let (+) (ls:Powers) (rs:Powers) =
let rec AddReversed (ls:Powers) (rs:Powers) =
match ( ls, rs ) with
| ( l::ltail, r::rtail ) -> ( l + r ) :: AddReversed ltail rtail
| ([], _) -> rs
| (_, []) -> ls
( AddReversed ( ls |> List.rev ) ( rs |> List.rev) ) |> List.rev
let Evaluate (ks:Powers) ( value:Complex ) =
ks |> List.fold (fun (acc:Complex) (k:double)-> acc * value + Complex.Create(k, 0.0) ) Complex.Zero
The following code fails in 'Evaluate' with:
"This expression was expected to have type Complex but here has type double list"
Am I breaking some rule on operator over-loading on '(+)'?
Things are OK if I change '(+)' to 'Add'.
open Microsoft.FSharp.Math
/// real power series [kn; ...; k0] => kn*S^n + ... + k0*S^0
type Powers = double List
let (+) (ls:Powers) (rs:Powers) =
let rec AddReversed (ls:Powers) (rs:Powers) =
match ( ls, rs ) with
| ( l::ltail, r::rtail ) -> ( l + r ) :: AddReversed ltail rtail
| ([], _) -> rs
| (_, []) -> ls
( AddReversed ( ls |> List.rev ) ( rs |> List.rev) ) |> List.rev
let Evaluate (ks:Powers) ( value:Complex ) =
ks |> List.fold (fun (acc:Complex) (k:double)-> acc * value + Complex.Create(k, 0.0) ) Complex.Zero
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
您代码的问题在于您对
+
的定义实际上隐藏了该运算符之前的所有定义,因此 F# 编译器认为+
只能用于添加>权力
值。这是因为包括 F# 运算符在内的函数值(使用let
声明)不支持重载。但是,如果将 F# 运算符添加为某种类型的
静态成员
,则可以重载它们。这不适用于缩写,因此您需要首先将类型声明更改为记录或可区分联合(我选择第二个选项)。然后您可以像这样实现重载运算符:请注意,该运算符现在被声明为
Powers
类型的一部分。由于该类型是可区分联合,因此我需要添加参数展开 (P ls, P rs
),然后再次包装结果。您的Evaluate
函数将如下所示:它再次需要解包值 (
P ks
),但其余代码保持不变。The problem with your code is that your definition of
+
actually hides all previous definitions of the operator, so the F# compiler thinks that+
can be used only for addition ofPowers
values. This is because function values (declared usinglet
) including F# operators do not support overloading.However, you can overload F# operators if you add them as a
static member
of some type. This doesn't work for abberviations, so you'll need to change the type declaration to a record or discriminated union first (I choose the second option). Then you can implement overloaded operator like this:Note that the operator is now declared as part of the
Powers
type. Since the type is a discriminated union, I needed to add unwrapping of parameters (P ls, P rs
) and then again wrap the result. YourEvaluate
function will look like this:It again needs to unwrap the value (
P ks
), but the rest of the code is unchanged.