Why does ML's Value Restriction stop you from capturing parametric values?
Your C# example doesn't trigger the value restriction at all. Here it is in OCaml:

# let foo f init acc = 
    let cur = ref init in
    (fun () -&gt; cur := f !cur acc ; !cur) ;;
val foo : ('a -&gt; 'b -&gt; 'a) -&gt; 'a -&gt; 'b -&gt; unit -&gt; 'a = &lt;fun&gt;

# let my_bar_a = foo (+) 0 1 ;;
val my_bar_a : unit -&gt; int = &lt;fun&gt;
# let my_bar_b = foo (^) ":" "-" ;;
val my_bar_b : unit -&gt; string = &lt;fun&gt;

# my_bar_a () ;;
- : int = 1
# my_bar_a () ;;
- : int = 2
# my_bar_b () ;;
- : string = ":-"
# my_bar_b () ;;
- : string = ":--"
# my_bar_a () ;;
- : int = 3
# my_bar_b () ;;
- : string = ":---"


Note that your initial example shouldn't trigger it either:

let f = fun x -&gt; x in f "plop", f 2 ;;
- : string * int = ("plop", 2)


f here is a non mutable value, it can be safely generalized.

The ML value restriction doesn't stop you from capturing parametric values as long as, given a unique reference, it will only be instantiated with a unique type. This is the case in your C# example: the reference cell is created for each new function.

I'm not extremely fond of the MLTON manual. You can read Real World OCaml for a decent introduction to the value restriction here. OCaml also has extensions to the value restriction when type parameters are in covariant position, which you can read about in Jacque Garrigue's paper.