Skip to content

Add "partitionMap" for List/Array/Seq/Set #1119

@SchlenkR

Description

@SchlenkR

Add "partitionMap" for List/Array/Seq/Set

I propose we add functions to the List/Array/Seq/Set modules that partition a collection of values into many collections of different types by a given mapper:

val partitionMap: mapper: ('a -> Choice<'b,'c>) -> source: 'a list -> 'b list * 'c list

Example (usage)

let evens,odds =
    [ 0..10 ] |> List.partitionMap (fun x ->
        let isEven = x % 2 = 0
        match isEven with
        | true -> Choice1Of2 x
        | false -> Choice2Of2 x)

// val odds: int list = [1; 3; 5; 7; 9]
// val evens: int list = [0; 2; 4; 6; 8; 10]

n partitions

There could exist partitionMap(n)s for more than 2 partitions (e.g. Choice is modeled for up to 7 choices):

val partitionMap3: mapper: ('a -> Choice<'b,'c,'d>) -> source: 'a list -> 'b list * 'c list * 'd list

Non-disjoint sets

Instead of mapping an input collection of n values to 2 collections of i, j values, where i + j = n, a more general approach could be mapping n values to collections where each collection has a maximun of n values:

// partitionMap for 3 non-disjoint partitions
val partitionMap3: mapper: ('a -> Option<'b> * Option<'c> * Option<'d>) -> source: 'a list -> 'b list * 'c list * 'd list

Example

let evens,odds,specials =
    [ 0..10 ] |> List.partitionMap3 (fun x ->
        let isEven = x % 2 = 0
        let isSpecial = x = 7
        
        let evenResult = if isEven then Some x else None
        let oddResult = if not isEven then Some x else None
        let specialResult = if isSpecial then Some (float x) else None
        
        evenResult, oddResult, specialResult
    )

// val evens: int list = [0; 2; 4; 6; 8; 10]
// val odds: int list = [1; 3; 5; 7; 9]
// val specials: float list = [7.0]

Alternatives

The existing way of approaching this problem in F# is composing existing List/Array/Seq functions, or by using FSharpPlus.

Links

  • The FSharpPlus implementation can be found here (in 2 versions: 1 using an optimized ListCollector for dotnet and another using recursion - thanks @gusty for the update).
  • A tweet adressing the proposal is here.

Pros and Cons

The advantages of making this adjustment to F# is having a useful function directly accessible in an idiomatic way without the need to resort to a package (FSharpPlus) or using hand-written code.

The disadvantages of making this adjustment to F# is: Having more and more functions in the core library could make it harder for beginners to see the essentials (which could be adressed by improved editor support).

Extra information

Estimated cost: XS - S

Affidavit

  • This is not a question (e.g. like one you might ask on stackoverflow) and I have searched stackoverflow for discussions of this issue
  • I have searched both open and closed suggestions on this site and believe this is not a duplicate
  • This is not something which has obviously "already been decided" in previous versions of F#. If you're questioning a fundamental design decision that has obviously already been taken (e.g. "Make F# untyped") then please don't submit it.

Please tick all that apply:

  • This is not a breaking change to the F# language design
  • I or my company would be willing to help implement and/or test this

For Readers

If you would like to see this issue implemented, please click the 👍 emoji on this issue. These counts are used to generally order the suggestions by engagement.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions