F# 对于在F中给出错误类型的二维数组中的循环#
我怀疑我在这里遗漏了一些非常明显的东西,但这不起作用:F# 对于在F中给出错误类型的二维数组中的循环#,f#,type-inference,F#,Type Inference,我怀疑我在这里遗漏了一些非常明显的东西,但这不起作用: let t = Array2D.create 1 1 1.0 for x in t do printfn "%f" x;; 它失败了 错误FS0001:类型“obj”与使用printf样式格式字符串产生的任何类型float、float32、decimal不兼容 有趣的是,使用printf“%A”或“%O”打印预期值,这向我表明问题在于类型推断 1D数组的相应代码工作正常 let t = Array.create 1 1.0 for x i
let t = Array2D.create 1 1 1.0
for x in t do printfn "%f" x;;
它失败了
错误FS0001:类型“obj”与使用printf样式格式字符串产生的任何类型float、float32、decimal不兼容
有趣的是,使用printf“%A”
或“%O”
打印预期值,这向我表明问题在于类型推断
1D数组的相应代码工作正常
let t = Array.create 1 1.0
for x in t do printfn "%f" x;;
作为参考,这是运行在.NET中最新mono上的2.0版(交互式和编译器),1D数组隐式实现了IList,这意味着它还实现了(通过继承)
IEnumerable
。所以,当你跑步时:
let t = Array.create 1 1.0
for x in t do printfn "%f" x;;
F#编译器从t
发出代码,从中获取IEnumerable
(seq
)的实现,然后对其进行迭代。由于它能够从数组中获取IEnumerable
,x
将具有类型T
另一方面,多维数组(2d、3d等)只实现IEnumerable
(而不是IEnumerable
),因此F#编译器将x
的类型推断为System.Object
(或obj
,在F#中)
有两种解决方案可满足您的需求:
在打印之前,在循环中强制转换每个值:
for x in t do printfn "%f" (x :?> float);;
for x in (Seq.cast<float> t) do printfn "%f" x;;
或者,使用Seq.cast创建并迭代强类型枚举数:
for x in t do printfn "%f" (x :?> float);;
for x in (Seq.cast<float> t) do printfn "%f" x;;
对于x in(Seq.cast t)不打印“%f”x;;
正如杰克指出的,这是一个问题。一个简单的解决方案是:
let t = Array2D.create 2 2 1.0
t |> Array2D.iter (printfn "%f");;
如果你真的喜欢..的。。在里面执行
语法:
type Array2DForLoopBuilder() =
member __.Zero() = ()
member __.For(a, f) = Array2D.iter f a
member __.Run e = e
let a2dfor = Array2DForLoopBuilder()
let t = Array2D.init 2 2 (fun a b -> float a + float b)
a2dfor { for x in t do printfn "%f" x }
有趣的是,编译器团队没有针对数组的特殊情况解决这个问题