F# 运算符重载:(+) 用于用户定义类型

发布于 2024-08-26 00:58:08 字数 749 浏览 2 评论 0原文

以下代码在“评估”中失败:
“该表达式预计具有 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 技术交流群。

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

发布评论

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

评论(1

感情洁癖 2024-09-02 00:58:08

您代码的问题在于您对 + 的定义实际上隐藏了该运算符之前的所有定义,因此 F# 编译器认为 + 只能用于添加 >权力值。这是因为包括 F# 运算符在内的函数值(使用 let 声明)不支持重载。

但是,如果将 F# 运算符添加为某种类型的静态成员,则可以重载它们。这不适用于缩写,因此您需要首先将类型声明更改为记录或可区分联合(我选择第二个选项)。然后您可以像这样实现重载运算符:

/// real power series [kn; ...; k0] => kn*S^n + ... + k0*S^0 
type Powers = 
  | P of double list 
  static member (+) (P ls, P rs) = 
    let rec AddReversed ls rs = 
        match ( ls, rs ) with 
        | ( l::ltail, r::rtail ) -> ( l + r ) :: AddReversed ltail rtail 
        | ([], _) -> rs 
        | (_, []) -> ls 
    P (( AddReversed ( ls |> List.rev ) ( rs |> List.rev) ) |> List.rev)

请注意,该运算符现在被声明为 Powers 类型的一部分。由于该类型是可区​​分联合,因此我需要添加参数展开 (P ls, P rs),然后再次包装结果。您的 Evaluate 函数将如下所示:

let Evaluate (P ks) ( value:Complex ) = 
  ks |> List.fold (fun (acc:Complex) (k:double)-> 
    acc * value +  Complex.Create(k, 0.0)  ) Complex.Zero

它再次需要解包值 (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 of Powers values. This is because function values (declared using let) 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:

/// real power series [kn; ...; k0] => kn*S^n + ... + k0*S^0 
type Powers = 
  | P of double list 
  static member (+) (P ls, P rs) = 
    let rec AddReversed ls rs = 
        match ( ls, rs ) with 
        | ( l::ltail, r::rtail ) -> ( l + r ) :: AddReversed ltail rtail 
        | ([], _) -> rs 
        | (_, []) -> ls 
    P (( AddReversed ( ls |> List.rev ) ( rs |> List.rev) ) |> List.rev)

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. Your Evaluate function will look like this:

let Evaluate (P ks) ( value:Complex ) = 
  ks |> List.fold (fun (acc:Complex) (k:double)-> 
    acc * value +  Complex.Create(k, 0.0)  ) Complex.Zero

It again needs to unwrap the value (P ks), but the rest of the code is unchanged.

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