如何在F#中扩展Array类型以支持Seq.sum函数
如何让
Seq.sum支持自定义加法的float array类型 尝试运行以下F#代码时,出现错误提示:
'Seq.sum' does not support the type 'float array', because the latter lacks the required (real or built-in) member 'op_Addition'open System.Runtime.CompilerServices [<Extension>] type ArrayExtension = static member inline Zero = Array.replicate 4 0. [<Extension>] static member inline (+)(m1: float array, m2: float array) = Array.map2 (fun m1 m2 -> m1 + m2) m1 m2 let res = Seq.replicate 4 (Array.replicate 4 0.) |> Seq.sum
问题原因
F#的Seq.sum函数依赖类型满足数值类型约束——要求类型本身定义static member (+)加法操作和static member Zero零值成员。而通过[<Extension>]定义的扩展方法,不属于类型本身的成员,无法被F#的类型类系统识别,因此Seq.sum无法找到对应的求和逻辑。
解决方案
方案1:定义包装类型实现数值约束
创建一个封装float array的自定义类型,直接在类型内部实现加法和零值成员,让Seq.sum能自动识别:
type Matrix4x4(values: float array) = member _.Values = values // 实现加法操作 static member inline (+)(m1: Matrix4x4, m2: Matrix4x4) = Matrix4x4(Array.map2 (+) m1.Values m2.Values) // 实现零值 static member inline Zero = Matrix4x4(Array.replicate 4 0.) // 转换为包装类型后使用Seq.sum let res = Seq.replicate 4 (Matrix4x4(Array.replicate 4 0.)) |> Seq.sum
方案2:用Seq.fold替代Seq.sum
直接利用已定义的扩展方法,通过Seq.fold手动实现求和逻辑,无需修改类型:
open System.Runtime.CompilerServices [<Extension>] type ArrayExtension = static member inline Zero = Array.replicate 4 0. [<Extension>] static member inline (+)(m1: float array, m2: float array) = Array.map2 (+) m1 m2 let res = Seq.replicate 4 (Array.replicate 4 0.) |> Seq.fold (+) ArrayExtension.Zero
内容的提问来源于stack exchange,提问作者Andrey
相关产品推荐
相关产品推荐

