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
在字符串类型的情况下没有多大意义.