Sorting a list into different bags according to predicate I've just started with F# (I'm coming from a mostly OO background) and I'm looking for 


feedback on the code, particularly: is this the way F# code should be written like?
have I overlooked an existing library function which would make this easier or could replace it completely?


The goal is: 

Take an input list and sort it according to certain conditions into several bags, keeping also those items not fitting any condition. (Which is why groupBy doesn't do the trick, unless I'm overlooking something).

The function:

let sortIntoBags&lt;'T, 'TBag&gt; (predicate: 'TBag*'T-&gt;bool) (bags: 'TBag list) 
(lst: 'T list)=
    let take (lst: 'T list) (bag: 'TBag)=
        let isInBag e = predicate (bag, e)
        let (inBag, remaining) = lst |&gt; List.partition isInBag
        ((bag, inBag), remaining)
    let (bagSets, leftOver) = bags |&gt; List.mapFold take lst
    (bagSets, leftOver)


A simple example for usage is:

&gt; let l= [1..25];;

val l : int list =
[1; 2; 3; 4; 5; 6; 7; 8; 9; 10; 11; 12; 13; 14; 15; 16; 17; 18; 19; 20; 21;
 22; 23; 24; 25]

&gt; let bags= [2; 3; 5; 7];;
val bags : int list = [2; 3; 5; 7]

&gt; let isDivisorFor (x, y) = 0=y%x ;;
val isDivisorFor : x:int * y:int -&gt; bool

&gt; l |&gt; sortIntoBags isDivisorFor bags;;
val it : (int * int list) list * int list =
([(2, [2; 4; 6; 8; 10; 12; 14; 16; 18; 20; 22; 24]); (3, [3; 9; 15; 21]);
(5, [5; 25]); (7, [7])], [1; 11; 13; 17; 19; 23])
Here's another (Subjectively better or worse) way to write this, however it does require comparison unlike yours:

let sortIntoBags&lt;'T,'TKey when 'TKey : comparison &gt; (predicate:'TKey*'T -&gt; bool) (bagKeys:'TKey list) (items:'T list) : ('TKey*'T list) list * 'T list =
    let bagMap:Map&lt;'TKey,'T list&gt; = bagKeys |&gt; Seq.map(fun k -&gt; k,List.empty) |&gt; Map.ofSeq
    items
    |&gt; List.rev
    |&gt; List.fold(fun (bagMap,unmatched:'T list) (item:'T) -&gt;
        match bagMap |&gt; Map.tryFindKey(fun k _ -&gt; predicate(k,item)) with
        | Some k -&gt; bagMap |&gt; Map.add k (item::bagMap.[k]), unmatched
        | None -&gt; bagMap,item::unmatched

    ) (bagMap,List.empty)
    |&gt; fun (m,x)-&gt;
        m |&gt; Map.toList, x


and the xunit tests I used to make sure it matched the output

open global.Xunit

[&lt;Fact&gt;]
let originalQuestion2 () =
   let l= [1..25]
   let bags= [2; 3; 5; 7]
   let isDivisorFor (x, y) = 0=y%x
   let expected = [(2, [2; 4; 6; 8; 10; 12; 14; 16; 18; 20; 22; 24]); (3, [3; 9; 15; 21]);(5, [5; 25]); (7, [7])], [1; 11; 13; 17; 19; 23]
   let actual = l |&gt; BagSort.sortIntoBags isDivisorFor bags
   printfn "%A" actual
   Console.Error.WriteLine(sprintf "%A" actual)
   Trace.WriteLine(sprintf "%A" actual)
   Assert.Equal(expected, actual)


[&lt;Fact&gt;]
let originalQuestionUnfolded2 () =
   let l= [1..25]
   let bags= [2; 3; 5; 7]
   let isDivisorFor (x, y) = 0=y%x
   let expected =
        let a =
            [   2, [2; 4; 6; 8; 10; 12; 14; 16; 18; 20; 22; 24]
                3, [3; 9; 15; 21]
                5, [5; 25]
                7, [7]
            ]
        let b = [1; 11; 13; 17; 19; 23]
        a,b
   let actual = l |&gt; BagSort.sortIntoBags isDivisorFor bags
   Assert.Equal(expected, actual)
   Assert.Equal((fst expected |&gt; fun x -&gt; x.[0]), fst actual |&gt; fun x -&gt; x.[0])