F#缺少类型约束
在以下代码中,请注意get_Zero的类型约束:F#缺少类型约束,f#,type-constraints,F#,Type Constraints,在以下代码中,请注意get_Zero的类型约束: type Wrapper<'t> = { Data : 't[] } let compute<'t when 't : (static member get_Zero : unit -> 't) and 't : (static member (~-) : 't -> 't) and 't : (static member (+) : 't * 't -> 't)>
type Wrapper<'t> = { Data : 't[] }
let compute<'t
when 't : (static member get_Zero : unit -> 't)
and 't : (static member (~-) : 't -> 't)
and 't : (static member (+) : 't * 't -> 't)>
(wrapper : Wrapper<'t>) =
wrapper.Data
|> Seq.mapi (fun i value -> (i, value))
|> Seq.sumBy (fun (i, value) ->
if i % 2 = 0 then value
else -value)
类型包装器
(wrapper:wrapper试图使下游静态成员约束显式化可能是一种挫折感,幸运的是,这几乎没有必要。只需标记函数inline
,然后让它们被推断出来即可
let inline compute (wrapper : Wrapper<_>) =
wrapper.Data
|> Seq.mapi (fun i value -> (i, value))
|> Seq.sumBy (fun (i, value) ->
if i % 2 = 0 then value
else -value)
让内联计算(包装器:包装器)=
包装器数据
|>Seq.mapi(乐趣i值->(i,值))
|>Seq.sumBy(乐趣(i,价值)->
如果i%2=0,则值
其他-价值)
正确的签名是:
let inline compute<'t
when 't : (static member Zero : 't)
and 't : (static member (~-) : 't -> 't)
and 't : (static member (+) : 't * 't -> 't)>
让内联计算
(您会注意到错误消息中的签名甚至不是有效的语法:when^t:(静态成员get_Zero:->^t)
。这就是我所说的令人沮丧的一部分。)为什么内联版本有效?编译器会推断出约束。sumBy
是内联的,它的约束也会通过将其标记为内联来传播到消费函数。这是有效的,但实际上并不能回答问题。它似乎也不适用于调用“计算”的类型扩展功能:类型Wrapper@brianberns:我用有效签名更新了我的答案。类型扩展不起作用,因为它使用了在类型上定义的泛型参数,并且类型级别泛型参数上的约束必须是显式的。除了这个问题已经有了非常有效的答案之外,我想在使用SRTP时强调一点(静态解析类型参数)在处理这些静态成员
等约束时,函数必须是内联的
,而不是使用'T
,而是使用^T
(意思是:^
,而不是”
)。另请参阅: