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