What / where get_Zero in F # int?

I am just learning F #, and playing tryfsharp.org , I noticed that if I change this code:

[0..100] |> List.sum 

to

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

I get the following error:

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

( Here is a script that you can run / modify in your browser , although it only works in IE for me!)

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

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

(note: it says “operator” and not “Member” in error, which may be related, although the definition of List.sum just says “member”).

+5
functional-programming f # compiler-errors f # -scripting
Jun 22 '13 at 13:01
source share
2 answers

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.

+8
Jun 22 '13 at 13:35
source share

Generally speaking, the F # specification is the best place to look for this kind of information. I believe this should be discussed in Section 14.5.4.1 (Modeling Solutions for Member Constraints), but it seems like Zero is not actually mentioned there, which is almost certainly a specification error.

+3
Oct 29 '13 at 13:55 on
source share



All Articles