f#的int中get_Zero是什么/在哪里?

时间:2013-06-22 13:01:49

标签: .net f# compiler-errors functional-programming f#-scripting

我只是在学习F#,在tryfsharp.org玩的时候,我注意到如果我改变了这段代码:

[0..100]
|> List.sum

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

我收到以下错误:

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

Here's the script that you can run/amend in your browser,虽然它似乎只适用于我的IE!)

当我查看the definition of List.sum时;它说类型必须有一个名为Zero的静态成员。这似乎解释了错误;除了我无法在int上看到任何名为Zero的成员!

因此;这个适用于整数的零成员在哪里?如果我输入int.,也不能输入the docs,我认为int不仅仅是一个.NET System.Int32(doesn't seem to have一个静态零属性)。< / p>

(注意:它确实在错误中说“运算符”而不是“成员”;这可能是相关的;虽然List.sum定义只是说“成员”)。

2 个答案:

答案 0 :(得分:8)

挖掘F#源代码,List.sum (and Seq.sum)正在使用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

另一方面,在查询Zero成员之前,F#编译器构建一个表来查找所有内置数值类型的零值。相关位在this line和下面的代码片段中。

    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

也就是说,如果您想在用户定义的类型上使用List.sum,则需要明确定义Zero成员。请注意,Zero在字符串类型的情况下没有多大意义。

答案 1 :(得分:3)

一般来说,F# specification是查找此类信息的最佳位置。我认为这应该在第14.5.4.1节(模拟成员约束的解决方案)中介绍,但看起来Zero实际上没有提到,这几乎肯定是规范错误。