読者です 読者をやめる 読者になる 読者になる

Foundations of F#を読む(4)

Foundations of F#を読む(3) - ZOETROPEの日記でfoldが理解できたので、次はunfold。

まず、unfoldの定義を見てみる。

val unfold   : ('b -> ('a * 'b) option) -> 'b -> IEnumerable<'a>

この定義を見てよく分からなかったのがoption型。これは何らかの値を持っている(Some)か、値を持っていない(None)かを表わすことができる型らしい。C#で言うところのNullableみたいなものかな。

HaskellではMaybeというらしい。http://itpro.nikkeibp.co.jp/article/COLUMN/20061205/255992/が詳しい。

1つ目の引数は、'bを引数に渡すと('a * 'b)というタプルのoptionを返す関数、2つ目の引数が、一番最初の種となる値。

そして、最初の種を関数に渡してタプルを生成、'aのほうを結果のリストに追加、b'のほうを次の関数への引数として渡す。これを繰り返して、結果のリストを作っていくと。

絵で描くとこんな感じかな。


下記の例を実行すると、1,2,3,4,・・・と数値が表示される。

#light
let nums = Seq.unfold (fun i -> Some (i, i + 1)) 1

let printSeq seq = Seq.iter (fun a -> printf "%d," a) seq

printSeq nums

でもこの例だと無限リストになってしまうので、途中で終了したいときはNoneを返してあげる。

下記の例では、1から100までのリストになる。

#light

let nums100 = Seq.unfold (fun i ->
  match i with
  | i when i <= 100 -> Some (i, i + 1)
  | _ -> None ) 1

let printSeq seq = Seq.iter (fun a -> printf "%d," a) seq

printSeq nums100  


前回のフィボナッチ数列を求めるプログラムは、種がタプルになっているだけ。なるほどー。