2
votes

In the following code, note the type constraint for 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)

Even though I already have an explicit type constraint, I'm still getting the following compiler error on the call to Seq.sumBy:

A type parameter is missing a constraint 'when ^t : (static member get_Zero : -> ^t)'

Anyone know what's going on here? Thanks.

1
Apart from this question already having a very valid answer, I'd like to stress that when you use SRTP (statically resolved type parameters) as you are doing with these static member etc constraints, then the function must be inline and instead of using 'T, use ^t instead (meaning: ^, not '). See also: docs.microsoft.com/en-us/dotnet/fsharp/language-reference/… - Abel

1 Answers

10
votes

Trying to make downstream static member constraints explicit can be an exercise in frustration, and, fortunately, it's seldom necessary. Just mark the function inline and let them be inferred.

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)

The correct signature is:

let inline compute<'t
            when 't : (static member Zero : 't)
            and 't : (static member (~-) : 't -> 't)
            and 't : (static member (+) : 't * 't -> 't)>

(You'll notice the signature in the error message isn't even valid syntax: when ^t : (static member get_Zero : -> ^t). This is part of what I mean by frustrating.)