gpt4 book ai didi

f# - 计算泛型类型的运行平均值

转载 作者:行者123 更新时间:2023-12-04 17:49:13 26 4
gpt4 key购买 nike

如果我可以在 F# 中使用类型类,我正在尝试做一些很容易的事情。

我希望能够计算我定义了加法、标量乘法和标量除法的任意类型的运行平均值。到目前为止,这是我的非编译尝试:

let updateMean<'a when 'a : (static member (*) : 'a -> float32 -> 'a) and 'a : (static member (/) : 'a -> float32 -> 'a) and 'a : (static member (+) : 'a -> 'a -> 'a)> (newObservation : 'a) (currentMean : 'a) (currentNumberOfRecords : int) =
(newObservation + (currentMean * (currentNumberOfRecords |> float32))) / float32 (1 + currentNumberOfRecords)

这是令人困惑的错误消息:
A type parameter is missing a constraint 'when ( ^a or  ^?766914) : (static member ( + ) :  ^a *  ^?766914 ->  ^?766915)'

最佳答案

如果你添加 inline,你可以走得更远。 (这是使用静态成员约束的要求)并将静态变量重命名为 'a^a (这是静态解析类型参数使用的语法)并删除约束的显式规范。然后编译器将尝试根据代码推断约束的类型(这使它更有用):

let inline updateMean (newObservation : ^a) (currentMean : ^a) 
(currentNumberOfRecords : int) =
(newObservation + (currentMean * (currentNumberOfRecords |> float32))) /
(float32 (1 + currentNumberOfRecords))

但是,这仍然不起作用,因为您限制了 currentMeanfloat32 - 通常,编译器要求运算符的两个参数具有相同的类型。您可以保留 currentNumberOfRecords作为相同类型的值 - 那么唯一棘手的部分是添加一个,这可以使用 LanguagePrimitives.GenericOne 来完成:
let inline updateMean newObservation currentMean currentNumberOfRecords =
(newObservation + (currentMean * currentNumberOfRecords)) /
(LanguagePrimitives.GenericOne + currentNumberOfRecords)

这很好用,但我可能会使用稍微不同的方法并将总和与总计数保持在一起(然后将它们除以得到平均值 - 这可能会具有更好的数值属性,因为您避免了重复舍入):
let inline updateState (currentSum, currentCount) newObservation = 
(currentSum + newObservation, currentCount + 1)

let inline currentMean (currentSum, currentCount) =
LanguagePrimitives.DivideByInt currentSum currentCount

诀窍是使用来自 LanguagePrimitives module 的操作。并让 F# 编译器自动找出类型约束(因为它们非常难看)。

关于f# - 计算泛型类型的运行平均值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21515223/

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