gpt4 book ai didi

f# - 可以扩展现有类型以使用 Seq.sum 等吗?

转载 作者:行者123 更新时间:2023-12-04 10:45:14 25 4
gpt4 key购买 nike

最近与很多 TimeSpans 一起工作,并且需要获得总和和平均值。
但是,TimeSpan 既没有定义操作符 get_Zero 也没有定义 DivideByInt,所以 Seq.sum 和 Seq.average 不能直接用于这种类型。以下无法编译:

open System
type System.TimeSpan
with
static member Zero with get() = TimeSpan()
static member (/) (n:DateTime, d:int) = DateTime( n.Ticks / (int64) d )

let ts = [ TimeSpan(10L); TimeSpan(99L) ]
let sum = ts |> Seq.sum
let avg = ts |> Seq.average
  • 错误:“TimeSpan”类型不支持任何名为“get_Zero”的运算符
  • 错误:“TimeSpan”类型不支持任何名为“DivideByInt”的运算符
  • 警告:扩展成员不能提供运算符重载。考虑将运算符定义为类型定义的一部分。

  • 是否有一些 F# 魔法可以在现有类型上定义这些运算符?

    我知道以下内容会起作用(并且应该更有效地启动),但我仍然对上述内容感到好奇,因此我可以将其添加到我的工具箱中以与其他类型一起使用。
    let sum = TimeSpan( ts |> Seq.sumBy (fun t -> t.Ticks) )
    let avg = TimeSpan( let len = ts |> Seq.length in sum.Ticks / int64 len )

    最佳答案

    据我所知,静态成员约束(由 Seq.sum 之类的函数使用)无法发现通过类型扩展(本质上是扩展方法)添加的成员,所以我认为没有直接的方法这样做。

    我能想到的最佳选择是围绕 System.TimeSpan 创建一个简单的包装器。结构。然后您可以定义所有必需的成员。代码如下所示:

    [<Struct>]
    type TimeSpan(ts:System.TimeSpan) =
    member x.TimeSpan = ts
    new(ticks:int64) = TimeSpan(System.TimeSpan(ticks))
    static member Zero = TimeSpan(System.TimeSpan.Zero)
    static member (+) (a:TimeSpan, b:TimeSpan) =
    TimeSpan(a.TimeSpan + b.TimeSpan)
    static member DivideByInt (n:TimeSpan, d:int) =
    TimeSpan(n.TimeSpan.Ticks / (int64 d))

    let ts = [ TimeSpan(10L); TimeSpan(99L) ]
    let sum = ts |> Seq.sum
    let avg = ts |> Seq.average

    我调用类型 TimeSpan ,所以它隐藏了标准 System.TimeSpan类型。但是,您仍然需要写 ts.TimeSpan当您需要访问底层系统类型时,这并不像它本来的那样好。

    关于f# - 可以扩展现有类型以使用 Seq.sum 等吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3223660/

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