Partitioning a list in F# based on whole group characteristics
Based on this answer from the Haskell version of this question, it looks like we can do something as simple as:

let partitionOn groupComplete list =
    let rec inner currentGroup remainingList =
        match (currentGroup, remainingList) with
        | (group, []) -&gt; [group]
        | (group, remaining) when groupComplete group -&gt; [group] @ (inner [] remaining)
        | (group, head::tail) -&gt; inner (group @ [head]) tail
    inner [] list


This simply recursively handles the three cases of: running out of elements; having a complete group; and building a group.

Update

Henrik Hansen pointed out that it is preferable to have a tail-recursive function. One possible way of achieving this is:

let partitionOn groupComplete list =
    let rec inner currentGroup remainingList =
        match remainingList with
        | [] -&gt; [currentGroup]
        | head::tail -&gt;
            let complete = groupComplete currentGroup
            let additionalGroup = if complete then [currentGroup] else []
            let newCurrentGroup = if complete then [] else currentGroup @ [head]
            let newRemaining = if complete then remainingList else tail
            additionalGroup @ (inner newCurrentGroup newRemaining)
    inner [] list


This merges together the last two cases of the match and gives a single call to inner at the end.

Update 2

If we look at the IL for this version, we can see that it is tail recursive:

    ...
    IL_0069: tail.
    IL_006b: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1&lt;!!0&gt; [FSharp.Core]Microsoft.FSharp.Core.Operators::op_Append&lt;class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1&lt;!!a&gt;&gt;(class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1&lt;!!0&gt;, class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1&lt;!!0&gt;)
    IL_0070: ret
    IL_0071: ldarg.1
    IL_0072: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1&lt;!0&gt; class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1&lt;class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1&lt;!!a&gt;&gt;::get_Empty()
    IL_0077: call class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1&lt;!0&gt; class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1&lt;class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1&lt;!!a&gt;&gt;::Cons(!0, class [FSharp.Core]Microsoft.FSharp.Collections.FSharpList`1&lt;!0&gt;)
    IL_007c: ret
} // end of method _::'inner@2-5'


Update 3

Nice idea to use a fold, from TheQuickBrownFox. This can be done more simply using the built-in fold function, keeping the same API:

let partitionOn groupComplete list =
    let folder acc x =
        match List.rev acc with
        | [] -&gt; [[x]]
        | current::rest when groupComplete current -&gt; acc @ [[x]]
        | current::rest -&gt; (List.rev rest) @ [current @ [x]]
    List.fold folder [] list


However, @ is O(n), whereas :: is O(1), so it should really be:

let partitionOn groupComplete list =
    let folder acc x =
        match acc with
        | [] -&gt; [[x]]
        | current::rest when groupComplete current -&gt; [x]::acc
        | current::rest -&gt; (x::current)::rest
    List.fold folder [] list |&gt; List.map List.rev |&gt; List.rev


Update 4

Based on TheQuickBrownFox comment the fold could be modified as follows:

let partitionOn initialGroupValue groupUpdate groupComplete list =
    let folder acc x =
        match acc with
        | ([], score) -&gt; ([[x]], groupUpdate score x)
        | (a, score) when groupComplete score -&gt; ([x]::a, groupUpdate initialGroupValue x)
        | (current::rest, score) -&gt; ((x::current)::rest, groupUpdate score x)
    List.fold folder ([], initialGroupValue) list |&gt; fst |&gt; List.map List.rev |&gt; List.rev


This version separates the current group evaluation into an update and a test, so that the minimum change is made for each iteration of the fold and the whole group doesn't need to be recalculated each time.