F#运算符(operator)重载: (+) for a user defind type

标签 f# operator-overloading

以下代码在“评估”中失败:
“预计此表达式将具有类型的复杂,但这里有双重列表”
我是否在“(+)”上违反了运算符(operator)的重载规则?
如果我更改'(+)'为“添加”。

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 

最佳答案

你的代码的问题是你的+的定义实际上隐藏了之前所有的操作符定义,所以F#编译器认为+只能用于加法Powers 值。这是因为包含 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),但其余代码不变。

关于F#运算符(operator)重载: (+) for a user defind type,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2450515/

相关文章:

f# - 为什么不识别指定值的模式匹配

math - F# 函数添加

logging - 关闭日志记录 F# 的优雅方式

javascript - 可以使用 websharper 作为 JS 的替代品吗?

c++ - 重载运算符的递归问题

c++ - 使用运算符重载 C++ 进行子类化

math - 将秒转换为日、时、分和秒

c++ - 在 C++ 中声明一个 operator+ 函数

c++ - 'friend' 函数和 << 运算符重载 : What is the proper way to overload an operator for a class?

c++ - 具有抽象继承的后缀运算符++