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 '-'
[test1/test1.fsproj]
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