Mutable state and procedural-style code are absolutely acceptable (and in fact encouraged) if they results in significant performance benefits. The core library code needs to be correct and performant before it needs to be idiomatic. Look at the implementation
of similar existing functions to see examples of this.

It is highly encouraged to do performance testing, and to provide comments in your pull request mentioning what testing you did, and what tradeoffs you encountered. This helps provide context to the community when reviewing the change, and helps provide
documentation to others as they embark on similar work.

It might be most efficient to use special-case handling when small collections are used as input, and to use a different or more general algorithm for larger collection. See, for example,
List.foldBack or Seq.windowed

Note the existence of optimized helpers and implementations (only legal in FSharp.Core) for List and Array in
local.fs e.g. inline IL, mutation of List elements. It might be appropriate to add to or consume these helpers.