Well you can make it tail recursive but then you have to reverse the list. You wouldn't want to fold it since it can exit out of the recursive loop at any time. I did a little testing and reversing the list is more than made up for by tail recursion.
// val pred : ('a list -> bool)
let split pred xs =
let rec split' l xs ys =
match xs with
| [] -> [], ys
| x::xs -> if pred (x::l) then (split' (x::l) xs (x::ys)) else x::xs, ys
let last, res = split' [] xs []
(res |> List.rev, last)
A version similar to Brian's that is tail recursive and takes a single value predicate.
// val pred : ('a -> bool)
let split pred xs =
let rec split' xs ys =
match xs with
| [] -> [], ys
| x::xs -> if pred x then (split' xs (x::ys)) else (x::xs), ys
let last, res = split' xs []
(res |> List.rev, last)
This is different from the library function partition in that it stops taking elements as soon as the predicate returns false kind of like Seq.takeWhile.
// library function
let x, y = List.partition (fun x -> x < 5) li
printfn "%A" x // [1; 3; 2; 4]
printfn "%A" y // [5; 7; 6; 8]
let x, y = split (fun x -> x < 5) li
printfn "%A" x // [1; 3]
printfn "%A" y // [5; 7; 2; 4; 6; 8]