How to calculate the "sliding sliced" fold of an array of int arrays in F#? - arrays

I have a function called calcArr_ArrOfArr in F# with the signature int [] -> int [][] -> int, i.e. calcArr_ArrOfArr takes two arguments, an int array and an array of int arrays, and returns an int.
I want to create the function calcArrOfArr with the signature int [][] -> int, which does the following:
let calcArrOfArr (arrOfArr : int [][]) =
Array.fold (fun acc e -> acc + (calcArr_ArrOfArr e arrOfArr.[?..])) 0 arrOfArr
where ? would be the index of e + 1.
In other words, in calcArrOfArr I want to apply calcArr_ArrOfArr to every element e of arrOfArr plus the "remaining portion" of arrOfArr, i.e. the slice of arrOfArr starting from after element e. Of course, for the last element of arrOfArr, nothing would be added to the accumulator, nor would an exception be thrown.
Is there a way to create calcArrOfArr in a functional way? An Array.foldi function would come handy...

If you feel you need Array.foldi, write one! The following snippet will extend the built-in Array module with a foldi:
module Array =
let foldi f z a =
a |> Array.fold (fun (i,a) x -> i+1, f i a x) (0,z) |> snd
Slicing from past-the-end gives you the empty array (i.e., [|0;1|].[2..] = [||]), so now your original suggestion works:
let calcArrOfArr (arrOfArr : int [][]) =
Array.foldi (fun i acc e -> acc + (calcArr_ArrOfArr e arrOfArr.[i+1..])) 0 arrOfArr
However, the slice arrOfArr.[i+1..] copies the array slice; this might be unfortunate for efficiency.

Haven't tested it, but this seems about right:
let calcArrOfArr (arrOfArr : int [][]) =
arrOfArr
|> Seq.mapi (fun i x -> i, x)
|> Seq.fold (fun acc (i, e) -> acc + (calcArr_ArrOfArr e arrOfArr.[i+1..])) 0

Related

F# write value in multidimensional array

I am trying to calculate covariance matrix
The operator 'expr.[idx]' has been used on an object of indeterminate
type based on information prior to this program point. Consider adding
further type constraints
CovMatrix.[a,b]
How to fix this and why it happens?
let FirstSeq = {1.0..10.0}
let SecondSeq = {20.0..30.0}
let All = seq {yield (0,FirstSeq); yield (1,SecondSeq)}
let cov(first:seq<float>)(second:seq<float>) =
Seq.map2 (*) first second
|> Seq.average
|> fun x -> x - Seq.average first * Seq.average second
let CreateCovMatrix(strangeList:seq<int * seq<float>>) =
let Size = Seq.length strangeList
let CovMatrix = Array2D.init Size Size
let CalculateCovMatrix =
for (a, i) in strangeList do
for (b, j) in strangeList do
CovMatrix.[a,b]=cov(i)(j)
CalculateCovMatrix
let result = CreateCovMatrix(All)
printf "%A" result
The function Array2D.init takes 3 parameters, you're missing the last one, which is the initialization function.
You can quick-fix it by writing:
let CovMatrix = Array2D.init Size Size (fun _ _ -> 0.)
Then you'll discover the next problem: assignment for mutable references is the <- operator, not = which is for comparison and let bindings.
So your function will look like this:
let CreateCovMatrix(strangeList:seq<int * seq<float>>) =
let Size = Seq.length strangeList
let CovMatrix = Array2D.init Size Size (fun _ _ -> 0.)
let CalculateCovMatrix =
for (a, i) in strangeList do
for (b, j) in strangeList do
CovMatrix.[a,b] <- cov(i)(j)
CalculateCovMatrix
But instead of specifying a function that ignores the inputs and return always zero, you can use the function Array2D.zeroCreate :
let CovMatrix = Array2D.zeroCreate Size Size
This kind of math is where functional programming excels,
although you're currently residing in the imperative paradigm. Gustavo handled your warnings, but even so your function won't give the desired result. Mixing functional and imperative concepts CreateCovMatrix now returns unit.
Good imperative:
let createCovMatrix(strangeList:seq<int * seq<float>>) =
let size = Seq.length strangeList
let covMatrix = Array2D.zeroCreate size size
for (a, i) in strangeList do
for (b, j) in strangeList do
covMatrix.[a,b]<-cov(i)(j)
covMatrix
Going functional:
let createCovMatrix strangeList =
strangeList
|> Seq.map (fun (a, i) -> Seq.map (fun (b, j) -> cov i j) strangeList)
|> array2D
Multi functional:
let createCovMatrix strangeList =
let mapper f = Seq.map f strangeList
mapper (fun (a, i) -> mapper (fun (b, j) -> cov i j))
|> array2D

Assign variable to array element where variable and array can be modified independently in ocaml

Here is the problem I can't get around, I'm working in ocaml to copy the elements of an array to a new array. I want to be able to modify these arrays independently from each other, but no matter what I try, a change to one array is reflected in the other array as well.
Here is a simplified example:
type sampleType = { a : int; b : int array };;
let x = {a = 5; b = [|1, 2, 3|] };;
let y = x.b;;
Array.set y 1 6;;
After running these commands I want:
y - : int array = [|1; 6; 3|]
x - : sampleType = {a = 5; b = [|1; 2; 3|]}
Instead x is being changed along with y, and
x - : sampleType = {a = 5; b = [|1; 6; 3|]}
Any solutions to this problem?
As you see from your experiments, this code:
let y = x.b
makes y refer to the very same array as x.b. It doesn't create an independent array. To create an independent array, you need to copy:
let y = Array.copy x.b
I was specifically using 3d arrays, realized I had to apply Array.copy at the lowest level of the 3d array, rather than at the top level.
let arr = Array.init 3 (fun _ -> Array.init 3 (fun _ -> (Array.init 3 (fun _ -> {faces = [|0;1;2;3;4|]}))));;
let drr = Array.init 3 (fun i -> Array.init 3 (fun j -> Array.copy arr.(i).(j)));;
This gave me the result I needed.

How to convert an Array2D with option int elements to Array2D with int elements

I am trying to convert Array2D optionArr with option int elements to Array2D arr with int elements:
let arr =
optionArr
|> Array2D.map (fun x ->
match Option.toArray x with
| [| |] -> -1
| [| v |] -> v)
However, Visual Studio 2013 underlines everything starting from Array2D.map ... until ... -> v) with red and says:
Type mismatch. Expecting a
int [,] option -> 'a
but given a
'b [,] -> 'c [,]
The type 'int [,] option' does not match the type ''a [,]'
I have been trying to "fix" my code but I no idea what I am doing wrong nor what the above error message alludes to.
EDIT
I applied Reed Copsey's answer (which itself uses Marcin's approach), yet still got the above error message when I realised that the message clearly states that Array2D arr is of type int [,] option and not int option [,]. Applying the same logic my corrected code is as follows:
let arr = defaultArg optionArr (Array2D.zeroCreate 0 0)
defaultArg seems to be quite useful for treating Option values as 'normal' ones.
Marcin's approach works fine. This can also be done a bit more simply using defaultArg directly:
// Create our array
let optionArr = Array2D.create 10 10 (Some(1))
let noneToMinusOne x = defaultArg x -1
let result = optionArr |> Array2D.map noneToMinusOne
let arr optionArr =
optionArr
|> Array2D.map (fun x ->
match x with
| Some(y) -> y
| None -> -1)
usage
let getOptionArr =
Array2D.create 10 10 (Some(1))
let result = arr getOptionArr

How to generate an array with a dynamic type in F#

I'm trying to write a function to return a dynamically typed array. Here is an example of one of the ways I've tried:
let rng = System.Random()
type ConvertType =
| AsInts
| AsFloat32s
| AsFloats
| AsInt64s
type InputType =
| Ints of int[]
| Float32s of float32[]
| Floats of float[]
| Int64s of int64[]
let genData : int -> int -> ConvertType -> InputType * int[] =
fun (sCount:int) (rCount:int) (ct:ConvertType) ->
let source =
match ct with
| AsInts -> Array.init sCount (fun _ -> rng.Next()) |> Array.map (fun e -> int e) |> Ints
| AsFloat32s -> Array.init sCount (fun _ -> rng.Next()) |> Array.map (fun e -> float32 e) |> Float32s
| AsFloats -> Array.init sCount (fun _ -> rng.Next()) |> Array.map (fun e -> float e) |> Floats
| AsInt64s -> Array.init sCount (fun _ -> rng.Next()) |> Array.map (fun e -> int64 e) |> Int64s
let indices = Array.init rCount (fun _ -> rng.Next sCount) |> Array.sort
source, indices
The problem I have is that on down when I use the function, I need the array to be the primitive type e.g. float32[] and not "InputType."
I have also tried doing it via an interface created by an inline function and using generics. I couldn't get that to work how I wanted either but I could have just been doing it wrong.
Edit:
Thanks for the great reply(s), I'll have to try that out today. I'm adding the edit because I solved my problem, although I didn't solve it how I wanted (i.e. like the answer). So an FYI for those who may look at this, I did the following:
let counts = [100; 1000; 10000]
let itCounts = [ 1000; 500; 200]
let helperFunct =
fun (count:int) (numIt:int) (genData : int -> int -> ('T[] * int[] )) ->
let c2 = int( count / 2 )
let source, indices = genData count c2
....
[<Test>]
let ``int test case`` () =
let genData sCount rCount =
let source = Array.init sCount (fun _ -> rng.Next())
let indices = Array.init rCount (fun _ -> rng.Next sCount) |> Array.sort
source, indices
(counts, itCounts) ||> List.Iter2 (fun s i -> helperFunct s i genData)
.....
Then each proceeding test case would be something like:
[<Test>]
let ``float test case`` () =
let genData sCount rCount =
let source = Array.init sCount (fun _ -> rng.Next()) |> Array.map (fun e -> float e)
let indices = Array.init rCount (fun _ -> rng.Next sCount) |> Array.sort
source, indices
.....
But, the whole reason I asked the question was that I was trying to avoid rewriting that genData function for every test case. In my real code, this temporary solution kept me from having to break up some stuff in the "helperFunct."
I think that your current design is actually quite good. By listing the supported types explicitly, you can be sure that people will not try to call the function to generate data of type that does not make sense (say byte).
You can write a generic function using System.Convert (which lets you convert value to an arbitrary type, but may fail if this does not make sense). It is also (very likely) going to be less efficient, but I have not measured that:
let genDataGeneric<'T> sCount rCount : 'T[] * int[] =
let genValue() = System.Convert.ChangeType(rng.Next(), typeof<'T>) |> unbox<'T>
let source = Array.init sCount (fun _ -> genValue())
let indices = Array.init rCount (fun _ -> rng.Next sCount) |> Array.sort
source, indices
You can then write
genDataGeneric<float> 10 10
but people can also write genDataGeneric<bool> and the code will either crash or produce nonsense, so that's why I think that your original approach had its benefits too.
Alternatively, you could parameterize the function to take a converter that turns int (which is what you get from rng.Next) to the type you want:
let inline genDataGeneric convertor sCount rCount : 'T[] * int[] =
let genValue() = rng.Next() |> convertor
let source = Array.init sCount (fun _ -> genValue())
let indices = Array.init rCount (fun _ -> rng.Next sCount) |> Array.sort
source, indices
Then you can write just getDataGeneric float 10 10 which is still quite elegant and it will be efficient too (I added inline because I think it can help here)
EDIT: Based on the Leaf's comment, I tried using the overloaded operator trick and it turns out you can also do this (this blog has the best explanation of what the hell is going on in the following weird snippet!):
// Specifies conversions that we want to allow
type Overloads = Overloads with
static member ($) (Overloads, fake:float) = fun (n:int) -> float n
static member ($) (Overloads, fake:int64) = fun (n:int) -> int64 n
let inline genDataGeneric sCount rCount : 'T[] * int[] =
let convert = (Overloads $ Unchecked.defaultof<'T>)
let genValue() = rng.Next() |> convert
let source = Array.init sCount (fun _ -> genValue())
let indices = Array.init rCount (fun _ -> rng.Next sCount) |> Array.sort
source, indices
let (r : float[] * _) = genDataGeneric 10 10 // This compiles & works
let (r : byte[] * _) = genDataGeneric 10 10 // This does not compile
This is interesting, but note that you still have to specify the type somewhere (either by usage later or using a type annotation). If you're using type annotation, then the earlier code is probably simpler and gives less confusing error messages. But the trick used here is certainly interesting.

Using Array.map on an array of arrays

I have an array of arrays P, which represents a Matrix, as an array of row vectors (that representation is more convenient for my purposes), and I want to extract the column-vector j of that array. My first pass was:
let column (M: float[][]) (j: int) =
Array.map(fun v -> v.[j]) M
This fails to compile, telling me that v.[j] is using operator expr.[idx] on an object of indeterminate type. This is puzzling to me, because hovering over v recognizes v as a float[], which I believe is a row vector.
Furthermore, the following code works:
let column (M: float[][]) (j: int) =
Array.map(fun v -> v) M
|> Array.map (fun v -> v.[j])
I fail to understand how the second example is different from the first one. The first map in the second example looks redundant: I am mapping an array to itself, and yet this seems to resolve the type determination problem.
Any help understanding what I am doing wrong or not seeing would be much appreciated!
The problem is that F# type inference is strictly left to right so that the compiler sees
let column (M: float[][]) (j: int) =
Array.map(fun v -> v.[j])
At this point, it knows absolutely nothing about v so it throws an error. This is why the forward pipe operator |> is so common - rewriting your code as
let column (M: float[][]) (j: int) =
M |> Array.map(fun v -> v.[j])
Is fine. This is also why your second example works
Since the type checker works from left to right, type of v is unspecified although type of M is available at some point later. Therefore:
let column (M: float[][]) (j: int) =
M |> Array.map (fun v -> v.[j])
or
let column M (j: int) =
Array.map (fun (v: float []) -> v.[j]) M
works.
In the second example, fun v -> v is ok on any type. So there is no problem with type of array elements. The second part with |> works as expected and demonstrates one more point why we should use pipe operators.

Resources