2012-02-27 106 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 }