mutable変数はクロージャに閉包できない

クロージャでかっこよく*1フィボナッチするよ!

let makeFiboClosure (a, b) =
    let mutable t = (a, b)
    fun () -> let x,y = t in t <- (y, x+y); x

makeFiboClosure は、クロージャを作る関数です。評価するとレキシカル変数なタプル t を更新しながら数列を生成する無引数のクージャを返します。
コンパイルしてみたら...

error FS0407: The mutable variable 't' is used in an invalid way.
Mutable variables cannot be captured by closures.
Consider eliminating this use of mutation or using a heap-allocated
mutable reference cell via 'ref' and '!'.

ダメでした。
「mutable 変数は クロージャでキャプチャできない。ref でヒープにアロケートして ! で参照してね」
なんて親切なエラーメッセージなんだ。

というわけで。完成。

let repeatedly f = seq {while true do yield f ()}

let makeFiboClosure (a, b) =
    let t = ref (a, b)
    fun () -> let x,y = !t in t := (y, x+y); x

let fibo = makeFiboClosure >> repeatedly
(1, 1) |> fibo |> Seq.take 10 |> Seq.toList
;; => [1; 1; 2; 3; 5; 8; 13; 21; 34; 55]

関数型プログラミングっぽいね!*2

*1:別にかっこよくはない

*2:いや副作用とかあるし