F#缺少类型约束

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)>

在以下代码中,请注意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)>
        (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
(意思是:
^
,而不是
)。另请参阅: