F#编译报错:带度量单位索引的包装数组相加时'Value无法编译期解析
问题根因
你的报错源于泛型参数'Value没有声明支持加法运算的静态解析约束。F#中的算术运算符属于静态成员约束范畴,要求编译阶段就可以确认对应类型实现了符合要求的运算签名,你当前的泛型声明没有为'Value附加该约束,因此编译器无法解析加法操作对应的具体实现。
解决方案
方案1:使用inline + 静态解析类型参数
给方法/函数添加inline修饰,配合显式的加法运算约束,让编译器在调用点根据实际传入的元素类型自动解析对应的加法实现:
类方法修改示例
type Arr<[<Measure>] 'Index, 'Value>(values: array<'Value>) = // 原有逻辑保持不变 let values = values |> Array.copy member internal _.Values = values member inline _.Add (x: ImArr<'Index, 'Value>) = if values.Length <> x.Values.Length then invalidArg (nameof x) "Cannot add arrays of different lengths" for idx = 0 to values.Length - 1 do values.[idx] <- values.[idx] + x.Values.[idx]
独立函数修改示例
module Helpers = let inline inPlaceAdd<[<Measure>] 'Index, ^Value when ^Value : (static member (+) : ^Value * ^Value -> ^Value)> (a: Arr<'Index, ^Value>) (b: ImArr<'Index, ^Value>) = let mutable i = 0 while i < a.Values.Length && i < b.Values.Length do a.Values.[i] <- a.Values.[i] + b.Values.[i] i <- i + 1
方案2:外部传入加法函数
如果不想使用inline,可以额外传入加法函数参数,把运算逻辑交给调用方指定,不需要依赖静态约束:
module Helpers = let inPlaceAdd<[<Measure>] 'Index, 'Value> (add: 'Value -> 'Value -> 'Value) (a: Arr<'Index, 'Value>) (b: ImArr<'Index, 'Value>) = let mutable i = 0 while i < a.Values.Length && i < b.Values.Length do a.Values.[i] <- add a.Values.[i] b.Values.[i] i <- i + 1 // 调用示例(元素为int类型时) // Helpers.inPlaceAdd (+) intArr intImArr
内容的提问来源于stack exchange,提问作者Matthew Crews
相关产品推荐
相关产品推荐

