代码之家  ›  专栏  ›  技术社区  ›  jyoung

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

  •  3
  • jyoung  · 技术社区  · 16 年前

    “evaluate”中的以下代码失败:
    “此表达式应具有复杂类型,但此处具有双重类型列表”
    我是否违反了有关运算符在'(+)'上过度加载的规则?
    如果我将'(+)改为'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 
    
    1 回复  |  直到 10 年前
        1
  •  9
  •   Tomas Petricek    16 年前

    代码的问题在于 + 实际上隐藏了运算符的所有先前定义,因此f编译器认为 + 只能用于添加 Powers 价值观。这是因为函数值(声明时使用 let )包括f运算符不支持重载。

    但是,如果将f运算符添加为 static member 某种类型的。这不适用于abervations,因此您需要首先将类型声明更改为记录或区分联合(我选择第二个选项)。然后可以实现这样的重载运算符:

    /// 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)
    

    请注意,该运算符现在声明为 权力 类型。因为类型是一个区分的联合,所以我需要添加参数的展开( 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 ,但其余代码不变。