Why "do...while" does not exist in F#
It turns out to be quite easy to write a good enough do-while in F# as a higher-order function:
let doWhile f c =
f ()
while c () do
f ()
break
and continue
would be a really useful feature additions; they're reserved words, and maybe we'll see them in a future version of the language. The lack of them is an occasional minor annoyance, but hardly makes the language 'unsuitable'. In the mean time, a mutable sentinel works, as you have in your example.
See also
http://tomasp.net/blog/imperative-ii-break.aspx/
F# is very much suitable for non-functional programming. In fact, being able to fine-tune parts of an algorithm in an imperative style is one of the major strong points of the language for me.
For example, in tackling a project euler problem, I started out with a clean functional solution using immutable sets and folds. It took 150 seconds to complete. Now having the framework of my algorithm in place allowed me to pick apart the data structures and folds operations one at a time until I managed to get the run time down to 5 seconds. My final solution was very much an imperative one (and even slightly faster than an equivalent C# version).
As you can see I solved it by coding a solution in functional style first and then rewrite small parts to an imperative style. Not having to deal with indices and other loop conditions explicitly kept the code more understandable for me.
Once you learn how to think like a functional programmer you'll find that you'll rarely want breaks and continues. That's what I experienced. But if you do need them, knowing how to think in a functional way helps in coming up with work-arounds, usually involving a tail-recursive version of what used to be a loop.
By the time you start thinking more in an idiomatic F# way, you'll probably see more and more (tail-)recursive code replacing what you used to do with looping constructs. Heck, writing F# for 2 years now has warped my mind so far that I'm more likely to pick recursion and folds over loops.
Whenever I think I need break/continue, I usually don't because there's a cleaner version of the algorithm hidden and waiting to get out. The biggest challenge is learning how to find that cleaner version. I'm afraid that lots of practice and good examples are the only way to get better at thinking functionally, but I believe that it's an effort well spent.
Edit: ironically, bubble sort is an algorithm which is actually designed for arrays with mutable contents. Any recursive bubble sort is likely to be harder to understand than an imperative version. I think I just killed my own post here.