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

Dan*_*eny 5 .net f# functional-programming compiler-errors f#-scripting

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

[0..100]
|> List.sum
Run Code Online (Sandbox Code Playgroud)

["A"; "B"; "D"]
|> List.sum
Run Code Online (Sandbox Code Playgroud)

我收到以下错误:

The type 'string' does not support the operator 'get_Zero'
Run Code Online (Sandbox Code Playgroud)

(这是你可以在你的浏览器中运行/修改的脚本,虽然它似乎只适用于我的IE!)

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

所以; 这个适用于整数的零成员在哪里?如果我输入int.,我也无法在intellisense中看到它,也不会在docs中看到它,因为int只是一个.NET System.Int32(它似乎没有静态Zero属性).

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

pad*_*pad 10

挖掘F#源代码,List.sum(和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
Run Code Online (Sandbox Code Playgroud)

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

    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
Run Code Online (Sandbox Code Playgroud)

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

  • 如果从数字的角度来看,`zero`对`string`没有意义; 但是,在`string`上有一个返回空字符串的`Zero`成员确实有意义,因为这会使`string`成为字符串连接下的一个monoid. (7认同)