Comparing 2 Array2Ds


the problem is to compare two Array2D arrays element by element stopping at the first element that fails.
I’ve spend a long time googling … the closest I’ve come to so far is this which won’t compile:

let isUneq a b =
    abs(a - b) > 0.1

let m = array2D [[1.1;2.0;3.0;4.0];[5.0;6.0;7.0;8.0]]
let n = array2D [[1.1;8.0;7.0;6.0];[5.0;4.0;3.0;2.0]]

let sm = seq { for x in m do yield x }
let sn = seq { for x in n do yield x }
let mm = Seq.forall2 isUneq sm sn
printf "mm is %A\n" mm

… which gives this compile error …

Program.fs(9,32): error FS0001: The type 'obj' does not support the operator '-'

so how do I create a sequence of the appropriate type (seq <float>) ??

If there is better solution to the problem - I’d love to know.


The simplest way to unblock you with minimal code changes is this:

let sm = seq { for x in m do unbox<float> x }
let sn = seq { for x in n do unbox<float> x }

This uses unbox to do an unsafe cast to float. If you try to cast to another type and evaluate the sequence there will be a runtime exception.

The problem is that Array2D isn’t really designed for use as an enumerable so it yields obj by default, which is basically a value with no type that the compiler can’t do anything useful with.

There isn’t a built-in Array2D function to make this easier unfortunately. To do it in a more type-safe way requires some boilerplate code to access the Array2D items by index. See here for an example: F# converting Array2D to array of arrays - Stack Overflow

You could add a helper function to convert an Array2D to a flat sequence and you would end up with this:

module Array2D =
    let toSeq arr = seq {
        for x in Array2D.base1 arr .. Array2D.length1 arr - 1 do
            for y in Array2D.base2 arr .. Array2D.length2 arr - 1 do
                yield arr.[x, y]

let isUneq a b =
    abs(a - b) > 0.1

let m = array2D [[1.1;2.0;3.0;4.0];[5.0;6.0;7.0;8.0]]
let n = array2D [[1.1;8.0;7.0;6.0];[5.0;4.0;3.0;2.0]]

let mm = Seq.forall2 isUneq (Array2D.toSeq m) (Array2D.toSeq n)
printf "mm is %A\n" mm