Delving into the F # source code, List.sum (and Seq.sum) uses 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 acc
On the other hand, the F # compiler builds a table to search for the null values of all built-in numeric types before querying Zero members. The corresponding bits are in this line and code snippet 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) else let pinfo = aty.GetProperty("Zero") unboxPrim<'T> (pinfo.GetValue(null,null)) static member Result : 'T = result
However, if you want to use List.sum for custom types, you need to explicitly specify the Zero member. Note that Zero doesn't make much sense in the case of a string type.
pad Jun 22 '13 at 13:35 2013-06-22 13:35
source share