Для циклов в 2D массивах, дающих неправильные типы в F # - PullRequest
0 голосов
/ 27 февраля 2012

Я подозреваю, что мне здесь не хватает чего-то очень очевидного, но это не работает:

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

Сбой при

Ошибка FS0001: Тип obj:несовместим с любыми типами float, float32, decimal, возникающими из-за использования строки формата printf

Интересно, что printf "%A" или "%O" выводит ожидаемые значения, которые мне подсказываютпроблема в выводе типа

Соответствующий код для одномерного массива работает нормально

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

Для справки это версия 2.0 (интерактивная и компиляторная версия), работающая на последней моно

Ответы [ 2 ]

8 голосов
/ 27 февраля 2012

В .NET массив 1D неявно реализует IList, что означает, что он также реализует (по наследству) IEnumerable<T>.Итак, когда вы запускаете:

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

, компилятор F # выдает код, который получает реализацию IEnumerable<T> (seq<T> в F #) из t, а затем перебирает его.Поскольку он может получить IEnumerable<T> из массива, x будет иметь тип T.

С другой стороны, многомерные массивы (2d, 3d и т. Д.) Реализуют только IEnumerable (не IEnumerable<T>), поэтому компилятор F # выводит тип x как System.Object (или obj в F #).

Существует два решения для того, что вы хотите:

Приведите каждое отдельное значение в цикле перед его печатью:

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

Или используйте Seq.cast для создания и итерации по строго типизированному перечислителю:

for x in (Seq.cast<float> t) do printfn "%f" x;;
3 голосов
/ 27 февраля 2012

Как указал Джек, это проблема.Одно простое решение:

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 }
...