F#に初挑戦。
最初はなんかC#っぽいF#になってたのだが、
yield! と seq {for .. do if ... then ...} を覚えたので、
関数型っぽくなってきた気がする。
もとにしたのはHaskellのワンライナー。
primes.hs
primes = 2:f [3,5..] where f (x:xs) = x:f [y | y <- xs, mod y x /= 0]
-
F#の配列は固定長。 [|1; 2; 3;|]
-
F#のリストは正格評価。 [1; 2; 3;] あるいは [1..3] と書く。
-
F#のシーケンスは遅延評価だけど、Haskellのリストとは結構違う。
一番違うのは、コンスセルではないこと。実態はIEnumerable<T>。headとtailに分けてパターンマッチできないらしいので注意。なんだかいろいろ書き方がある。
個々の要素をシーケンスにするには、seq [1; 2; 3;] 。
範囲指定なら seq {1..3} または seq [1..3] または {1..3} 。
yieldを含む場合は seq { yieldを含む式 } または seq [ yieldを含む式 ] 。シーケンス式の中でシーケンスをyieldするには、yield! とやるといいらしい。
primes.fs
open System
let primes =
let odds = Seq.initInfinite (fun i -> 2 * i + 1)
let rec f src =
let (x, xs) = (Seq.head src, Seq.skip 1 src)
seq {yield x; for i in f xs do if i % x <> 0 then yield i}
seq {yield 2; yield! f (Seq.skip 1 odds)}
let list = primes |> Seq.take 10 |> Seq.toList
printfn "%A" list
ちなみに、シーケンスじゃなくて遅延リストが欲しい人は、F# PowerPackのLazyListを使うといい。