Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

FS-1135 - Random functions for collections #732

Merged
merged 18 commits into from
May 29, 2024
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 22 additions & 1 deletion RFCs/FS-1135-random-functions-for-collections.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ This feature is motivated by the following use cases:
The following general rules are applied to all functions
- New functions should be implemented in `List`, `Array`, `Seq` modules
- Each function should have a variant that takes a [Random](https://learn.microsoft.com/en-us/dotnet/api/system.random) argument
- Each function should have a variant that takes a custom `randomizer` function. This function should return a `float` value from `0..1` range sampled from the desired distribution.
abelbraaksma marked this conversation as resolved.
Show resolved Hide resolved
- Custom shared thread-safe `Random` instance should be used for function without `Random` argument (since `Random.Shared` is only available since .NET 6)

### Shuffle
Expand All @@ -41,17 +42,23 @@ The following functions will be added to each module.
// Array module
val randomShuffle: array:'T[] -> 'T[]
val randomShuffleWith: random:Random -> array:'T[] -> 'T[]
val randomShuffleBy: randomizer: (unit -> float) -> array:'T[] -> 'T[]
val randomShuffleInPlace: array:'T[] -> 'T[]
val randomShuffleInPlaceWith: random:Random -> array:'T[] -> 'T[]
val randomShuffleInPlaceBy: randomizer: (unit -> float) -> array:'T[] -> 'T[]
// List module
val randomShuffle: list:'T list -> 'T list
val randomShuffleWith: random:Random -> list:'T list -> 'T list
val randomShuffleBy: randomizer: (unit -> float) -> list:'T list -> 'T list
// Seq module
val randomShuffle: source:'T seq -> 'T seq
val randomShuffleWith: random:Random -> source:'T seq -> 'T seq
val randomShuffleBy: randomizer: (unit -> float) -> source:'T seq -> 'T seq
```
[ArgumentNullException](https://learn.microsoft.com/en-us/dotnet/api/system.argumentnullexception) is raised if collection is `null`, or if the `random` argument is `null`.

[ArgumentOutOfRangeException](https://learn.microsoft.com/en-us/dotnet/api/system.argumentoutofrangeexception) is raised if randomizer returns a value outside the `0..1` range.
abelbraaksma marked this conversation as resolved.
Show resolved Hide resolved

Example:
```fsharp
let allPlayers = [ "Alice"; "Bob"; "Charlie"; "Dave" ]
Expand All @@ -68,17 +75,22 @@ The following functions will be added to each module.
// Array module
val randomChoice: array:'T[] -> 'T
val randomChoiceWith: random:Random -> array:'T[] -> 'T
val randomChoiceBy: randomizer: (unit -> float) -> array:'T[] -> 'T
// List module
val randomChoice: list:'T list -> 'T
val randomChoiceWith: random:Random -> list:'T list -> 'T
val randomChoiceBy: randomizer: (unit -> float) -> list:'T list -> 'T
// Seq module
val randomChoice: source:'T seq -> 'T
val randomChoiceWith: random:Random -> source:'T seq -> 'T
val randomChoiceBy: randomizer: (unit -> float) -> source:'T seq -> 'T
```
[ArgumentNullException](https://learn.microsoft.com/en-us/dotnet/api/system.argumentnullexception) is raised if collection is `null`, or if the `random` argument is `null`.

[ArgumentException](https://learn.microsoft.com/en-us/dotnet/api/system.argumentexception) is raised if collection is empty.

[ArgumentOutOfRangeException](https://learn.microsoft.com/en-us/dotnet/api/system.argumentoutofrangeexception) is raised if randomizer returns a value outside the `0..1` range.
abelbraaksma marked this conversation as resolved.
Show resolved Hide resolved

Example:
```fsharp
let allPlayers = [ "Alice"; "Bob"; "Charlie"; "Dave" ]
Expand All @@ -95,19 +107,24 @@ The following functions will be added to each module.
// Array module
val randomChoices: count:int -> array:'T[] -> 'T[]
val randomChoicesWith: random:Random -> count:int -> array:'T[] -> 'T[]
val randomChoicesBy: randomizer: (unit -> float) -> count:int -> array:'T[] -> 'T[]
// List module
val randomChoices: count:int -> list:'T list -> 'T list
val randomChoicesWith: random:Random -> count:int -> list:'T list -> 'T list
val randomChoicesBy: randomizer: (unit -> float) -> count:int -> list:'T list -> 'T list
// Seq module
val randomChoices: count:int -> source:'T seq -> 'T seq
val randomChoicesWith: random:Random -> count:int -> source:'T seq -> 'T seq
val randomChoicesBy: randomizer: (unit -> float) -> count:int -> source:'T seq -> 'T seq
```
[ArgumentNullException](https://learn.microsoft.com/en-us/dotnet/api/system.argumentnullexception) is raised if collection is `null`, or if the `random` argument is `null`.

[ArgumentException](https://learn.microsoft.com/en-us/dotnet/api/system.argumentoutofrangeexception) is raised if N is negative.

abelbraaksma marked this conversation as resolved.
Show resolved Hide resolved
[ArgumentException](https://learn.microsoft.com/en-us/dotnet/api/system.argumentexception) is raised if collection is empty.

[ArgumentOutOfRangeException](https://learn.microsoft.com/en-us/dotnet/api/system.argumentoutofrangeexception) is raised if randomizer returns a value outside the `0..1` range.
abelbraaksma marked this conversation as resolved.
Show resolved Hide resolved

Example:
```fsharp
let allPlayers = [ "Alice"; "Bob"; "Charlie"; "Dave" ]
Expand All @@ -124,19 +141,23 @@ The following functions will be added to each module.
// Array module
val randomSample: count:int -> array:'T[] -> 'T[]
val randomSampleWith: random:Random -> count:int -> array:'T[] -> 'T[]
val randomSampleBy: randomizer: (unit -> float) -> count:int -> array:'T[] -> 'T[]
// List module
val randomSample: count:int -> list:'T list -> 'T list
val randomSampleWith: random:Random -> count:int -> list:'T list -> 'T list
// Seq module
val randomSample: count:int -> source:'T seq -> 'T seq
val randomSampleWith: random:Random -> count:int -> source:'T seq -> 'T seq
val randomSampleBy: randomizer: (unit -> float) -> count:int -> source:'T seq -> 'T seq
```
[ArgumentNullException](https://learn.microsoft.com/en-us/dotnet/api/system.argumentnullexception) is raised if collection is `null`, or if the `random` argument is `null`.

[ArgumentException](https://learn.microsoft.com/en-us/dotnet/api/system.argumentoutofrangeexception) is raised if N is greater than collection length or is negative.

[ArgumentException](https://learn.microsoft.com/en-us/dotnet/api/system.argumentexception) is raised if collection is empty.

abelbraaksma marked this conversation as resolved.
Show resolved Hide resolved
[ArgumentOutOfRangeException](https://learn.microsoft.com/en-us/dotnet/api/system.argumentoutofrangeexception) is raised if randomizer returns a value outside the `0..1` range.
abelbraaksma marked this conversation as resolved.
Show resolved Hide resolved

Example:
```fsharp
let allPlayers = [ "Alice"; "Bob"; "Charlie"; "Dave" ]
Expand Down Expand Up @@ -195,4 +216,4 @@ N/A

# Unresolved questions

[Additional function suggested](https://github.com/fsharp/fslang-design/discussions/731#discussioncomment-9328918)
N/A