Take the 2-minute tour ×

I'm just learning F#, and while playing at tryfsharp.org I noticed that if I change this code:

|> List.sum


["A"; "B"; "D"]
|> List.sum

I get the following error:

The type 'string' does not support the operator 'get_Zero'

(Here's the script that you can run/amend in your browser, though it only seems to work in IE for me!)

When I checked the definition of List.sum; it says that the type must have a static member called Zero. This seems to explain the error; except for the fact that I can't see any member called Zero on int!

So; where is this Zero member that applies to ints? I can't see it in intellisense if I type int., nor in the docs, which says int is just a .NET System.Int32 (which doesn't seem to have a static Zero property).

(note: it does say "Operator" and not "Member" in the error; which may be related; though the List.sum definition does just say "member").

share|improve this question

2 Answers 2

up vote 6 down vote accepted

Digging in F# source code, List.sum (and Seq.sum) is using GenericZero:

let inline sum (source: seq< (^a) >) : ^a = 
    use e = source.GetEnumerator() 
    let mutable acc = LanguagePrimitives.GenericZero< (^a) >
    while e.MoveNext() do
        acc <- Checked.(+) acc e.Current

On the other hand, F# compiler builds a table to lookup zero values of all built-in numeric types before querying Zero members. The relevant bits are in this line and the code fragment below.

    type GenericZeroDynamicImplTable<'T>() = 
        static let result : 'T = 
            // The dynamic implementation
            let aty = typeof<'T>
            if   aty.Equals(typeof<sbyte>)      then unboxPrim<'T> (box 0y)
            elif aty.Equals(typeof<int16>)      then unboxPrim<'T> (box 0s)
            elif aty.Equals(typeof<int32>)      then unboxPrim<'T> (box 0)
            elif aty.Equals(typeof<int64>)      then unboxPrim<'T> (box 0L)
            elif aty.Equals(typeof<nativeint>)  then unboxPrim<'T> (box 0n)
            elif aty.Equals(typeof<byte>)       then unboxPrim<'T> (box 0uy)
            elif aty.Equals(typeof<uint16>)     then unboxPrim<'T> (box 0us)
            elif aty.Equals(typeof<uint32>)     then unboxPrim<'T> (box 0u)
            elif aty.Equals(typeof<uint64>)     then unboxPrim<'T> (box 0UL)
            elif aty.Equals(typeof<unativeint>) then unboxPrim<'T> (box 0un)
            elif aty.Equals(typeof<decimal>)    then unboxPrim<'T> (box 0M)
            elif aty.Equals(typeof<float>)      then unboxPrim<'T> (box 0.0)
            elif aty.Equals(typeof<float32>)    then unboxPrim<'T> (box 0.0f)
               let pinfo = aty.GetProperty("Zero")
               unboxPrim<'T> (pinfo.GetValue(null,null))
        static member Result : 'T = result

That said, if you would like to use List.sum on user-defined types, you need to define Zero member explicitly. Note that Zero doesn't make much sense in case of string type.

share|improve this answer
Zero doesn't make sense on string if you think of it in terms of numerics; however, it does make sense to have a Zero member on string which returns the empty string, as that would make string a monoid under string concatenation. –  Jack P. Jun 22 '13 at 13:38
Ok, this makes sense. Ofcourse, I didn't expect the code to work for a string array, I was just trying to understand how things worked. I'm curious why this magic Zero member that seems to be defined in the code linked doesn't seem accessible/visible in any of the intellisense as a visible member; is this just because it's not defined in a way that's visible outside of the type/module/etc.? –  Danny Tuppeny Jun 22 '13 at 13:42
@DannyTuppeny Yes, that's exactly the reason. It's only for the built-in, primitive numeric types in the list @pad posted -- any other types will have an actual property called Zero with a getter (get) method you can call (i.e., get_Zero). –  Jack P. Jun 22 '13 at 15:12

Generally speaking, the F# specification is the best place to look for this sort of information. I believe that this should be covered in section (Simulation of Solutions for Member Constraints), but it looks like Zero isn't actually mentioned there, which is almost certainly a spec bug.

share|improve this answer

Your Answer


