2012-02-27 93 views
0

我怀疑,我失去了一些东西很明显这里,但这个不起作用:对于二维数组循环给不正确类型的F#

let t = Array2D.create 1 1 1.0 
for x in t do printfn "%f" x;; 

它失败

错误FS0001:本键入“OBJ”不兼容的任何类型的浮动,FLOAT32,十进制,有趣的是使用从使用printf风格格式字符串

所产生210个或"%O"打印期望值这表明对我来说,问题是与类型推断

为一维数组。相应代码工作正常

let t = Array.create 1 1.0 
for x in t do printfn "%f" x;; 

作为参考,这是在2.0版(交互式和编译器)运行在最新的单声道

回答

8

在.NET中,一维数组隐含地实现了IList,这意味着它也实现(通过继承)IEnumerable<T>。所以,当你运行:

let t = Array.create 1 1.0 
for x in t do printfn "%f" x;; 

F#编译器发出的代码从t在它得到的IEnumerable<T>seq<T>在F#)的实现,然后遍历。因为它是能够从阵列得到IEnumerable<T>x将有类型T

在另一方面,多维阵列(二维,三维等)仅实现IEnumerable(未IEnumerable<T>),所以F#编译器推断作为System.Objectx类型(或obj,在F#)。

有你想要的东西两个解决方案:

演员循环中的每个单独的值,可以在打印前:

for x in t do printfn "%f" (x :?> float);; 

或者,使用Seq.cast创建和遍历一个强类型的普查员:

for x in (Seq.cast<float> t) do printfn "%f" x;; 
+1

有意思的是,在编译器团队并没有解决这个特殊情况下的阵列 – 2012-02-27 07:20:55

3

正如杰克指出的,这是一个问题米一个简单的解决方法是:

let t = Array2D.create 2 2 1.0 
t |> Array2D.iter (printfn "%f");; 

如果你真的for .. in .. do语法:

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 }