Reputation: 2911
I am new to programming and F# is my first language.
Here are the relevant parts of my code:
let rec splitArrayIntoGroups (inputArray: string[]) (groupSize: int) (hashSetOfGroups: HashSet<string[]>)=
let startIndex = 0
let endIndex = groupSize - 1
let group = inputArray.[startIndex .. endIndex]
let nextInputArray = inputArray.[groupSize .. inputArray.Length - 1]
hashSetOfGroups.Add(group) |> ignore
splitArrayIntoGroups nextInputArray groupSize hashSetOfGroups
let hashSetOfGroups = new HashSet<string[]>()
splitArrayIntoGroups urlArray 10 hashSetOfGroups
urlArray is an array of almost 3200 URLs.
When I try to run the code in F# interactive, I receive the following error message:
Program.fs(119,1): error FS0030: Value restriction. The value 'it' has been inferred to have generic type val it : '_a Either define 'it' as a simple data term, make it a function with explicit arguments or, if you do not intend for it to be generic, add a type annotation.
What went wrong, and what changes should I make?
Upvotes: 1
Views: 1104
Reputation: 2764
As it stands, the code will loop indefinitely. What is the exit condition? As @Petr points out, what does the function return?
Below is a version which exits and returns unit when the inputArray is empty:
let rec splitArrayIntoGroups (inputArray: string[]) (groupSize: int) (hashSetOfGroups: HashSet<string[]>)=
match inputArray with
| [||] -> ()
| _ ->
let startIndex = 0
let endIndex = groupSize - 1
let group = inputArray.[startIndex .. endIndex]
let nextInputArray = inputArray.[groupSize .. inputArray.Length - 1]
hashSetOfGroups.Add(group) |> ignore
splitArrayIntoGroups nextInputArray groupSize hashSetOfGroups
Rather than using a mutable set, a more idiomatic way would be to use the F# Set
type and then pass a new version to each recursion, like this:
let rec splitArrayIntoGroups2 inputArray groupSize hashSetOfGroups =
match inputArray with
| [||] -> hashSetOfGroups
| _ ->
let startIndex = 0
let endIndex = groupSize - 1
let group = inputArray.[startIndex .. endIndex]
let nextInputArray = inputArray.[groupSize .. inputArray.Length - 1]
let newSet = Set.add group hashSetOfGroups
splitArrayIntoGroups2 nextInputArray groupSize newSet
Btw, the logic as it stands appears to be buggy re the index logic. If I try the following:
let urlArray = [| "a"; "b"; "c"; "d" |]
let result = splitArrayIntoGroups2 urlArray 10 Set.empty
then I get an IndexOutOfRangeException
.
Did you mean something like this instead?
let rec splitArrayIntoGroups3 inputArray startIndex groupSize hashSetOfGroups =
let maxIndex = Array.length inputArray - 1
if startIndex > maxIndex then
hashSetOfGroups
else
let endIndex = min (startIndex + groupSize - 1) maxIndex
let group = inputArray.[startIndex .. endIndex]
let newSet = Set.add group hashSetOfGroups
let nextStartIndex = endIndex + 1
splitArrayIntoGroups3 inputArray nextStartIndex groupSize newSet
let urlArray = [| "a"; "b"; "c"; "d"; "e" |]
let result = splitArrayIntoGroups3 urlArray 0 2 Set.empty
Note that this final version works with arrays of any type, not just string arrays.
Upvotes: 5