Just wanted to share a couple little functions that I was playing with since it made my code terse and readable. At first I needed a way to fold a function until a predicate. This way I could stop and didn’t have to continue through the whole list. Then I needed to be able to do the same kind of thing but choosing all elements up until a predicate.
First, folding. I wanted to be able to get all the characters up until white space. For example:
let (++) a b = a.ToString() + b.ToString() let upToSpaces str = foldTill Char.IsWhiteSpace (++) "" str
Which led me to write the following fold function. Granted it’s not lazy evaluated, but for me that was OK.
let foldTill check predicate seed list= let rec foldTill' acc = function |  -> acc | (h::t) -> match check h with | false -> foldTill' (predicate acc h) t | true -> acc foldTill' seed list
Running this gives
> upToSpaces "abcdef gh";; val it : string = "abcdef"
Here’s a more general way of doing it for sequences. Granted it has mutable state, but its hidden in the function and never leaks. This is very similar to how fold is implemented in F# core, I just added the extra check before it calls into the fold predicate
let foldTill check predicate seed (source:seq<'a>) = let finished = ref false use e = source.GetEnumerator() let mutable state = seed while e.MoveNext() && not !finished do match check e.Current with | false -> state <- predicate state e.Current | true -> finished := true state