スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

F#入門第48回(seq (1))

今回のお題は「seq (1)」です。
 
seqというのは、seqence(数列)の頭文字で、同一の型のものが並んでいるものです。この型をTとすると,seq<T>と表されます。
seq<T>型は.NETでいうところのIEnumerable<T>というインターフェイスの別名です。(enumerableというのは日本語では、可算で「一つ二つと数えられる」ということです。

まずはルールを指定してsequenceを作成してみましょう。
ここで、よく使われるのがSeq.unfold関数です。この関数は一般性がある分、使い方がややこしいと思うので少し説明したいと思います。
まずsequenceを作成していくのですが、直接、項を入れていくのではなくて、ワンクッションおいて、項を作り出しては入れていきます。まずstate(状態)というのを考えます。
そして次々にあるルールで状態が変わっていくことを考えます。
次の図を見てください.
 
状態0 ⇒最初の項

状態1⇒次の項

状態2⇒その次の項

 
つまり、「状態から、次の状態へ移るルールと状態からseqeunceに入れる値を決めるルール」があれば、あとは最初の状態0の値があればsequenceは一意的に作ることができるわけです。
ここで、「状態から、次の状態へ移るルールと状態からseqeunceに入れる値を決めるルール」を一つの関数で表します。
fun 状態 -> (seqeunceに入れる値,次の状態) という形です。
 
例1
状態 sequenceの項
1  ⇒ 2

2  ⇒ 4

3  ⇒ 6
 
ならば、関数は fun n -> ( 2*n , n+1 ) 初期値は1
 
例2
状態 sequenceの項
1  ⇒ "1"

2  ⇒ "2"

3  ⇒ "3"
 
ならば、関数は fun n -> ( n.ToString() , n+1 ) 初期値は1
 
例3
状態 sequenceの項
(1,1)  ⇒ 1

(1,2)  ⇒ 1

(2,3)  ⇒ 2

(3,5)  ⇒ 3

(5,8)  ⇒ 5
 
ならば、関数は fun (n1,n2) -> ( n1 ,(n2 , n1 + n2) ) 初期値は(1,1)となります。
 
なお、返り値をoption型にしてやるとSome(a)のときはsuquenceに追加され、Noneが返されるとそこで追加が停止しそれ以降は追加されません。
 
それでは上の例について、追加停止条件を適当に設定して実行してみます。
 
例1
 
let ex01 = Seq.unfold 
                (fun n ->
                    if (n < 4 ) then Some(2 * n, n + 1) 
                    else None) 
                1
 
> ex01;;
val it : seq<int> = seq [2; 4; 6]
 
例2
 
let ex02 = Seq.unfold 
                (fun n ->
                    if (n < 8 ) then Some(n.ToString() , n + 1) 
                    else None) 
                1
 
> ex02;;
val it : seq<string> = seq ["1"; "2"; "3"; "4"; ...]
 
例3
 
let ex03 = Seq.unfold 
                (fun (n1,n2) ->
                    if (n1 < 7 ) then Some(n1,(n2,n1+n2)) 
                    else None) 
                (1,1)
                
 
> ex03;;
val it : seq<int> = seq [1; 1; 2; 3; ...]
 
(例3はいわゆるフィボナッチ数列のseqを作成しています。)
 
listやarrayにはunfold関数がないのですが、Seq.to_listやSeq.to_array関数で簡単にSeq<T>型から、list<T>,array<T>型に変換できます。
 
 
宿題
let nums = Seq.unfold (fun num ->
    if (num < 2 || (2 < num && num < 10) ) then Some(num.ToString(), num + 1) else None) 0
で出来上がるnumsはどんなものでしょうか。

スポンサーサイト

テーマ : プログラミング
ジャンル : コンピュータ

コメントの投稿

非公開コメント

Sequence expressions

>seqは seq[ と ] で囲まれます。
リストは、シーケンスで、seq リストとすることで、シーケンスにできますから、間違いではないですが、
http://research.microsoft.com/en-us/um/cambridge/projects/fsharp/manual/spec2.aspx#_Toc207785615
によると、シーケンスは、
seq { … }
です。

>右辺にもseqがついて欲しいのですが
例えば、
seq { 'a'..'e' }
のような場合は付きます。
同じようでも
seq ['a'..'e']
ではつきません。

No title

御指摘ありがとうございます。なんか、この辺はインターフェイスとしてのseqと、そのインターフェイスを利用して作成するseqのあたりでややこしいですね。(単に私の理解不足かも。)とりあえず、問題部分は削除しました。
lowlanderさんのページhttp://lowlander256.web.fc2.com/fsharp/data_processing.htmlでは、そのあたり、詳しいです。

seq

リンク先、いいですね。
勉強になります。

>インターフェイスとしてのseqと、そのインターフェイスを利用して作成するseqのあたりでややこしいですね。
seq って、結局(seq;; //とかしてみると分かる)
(seq<'a> -> seq<'a>)
の関数なので、構文なのかどうなのか(単なるキャスト的なものかコンストラクタ的なものなのか?とか)ありますね。
(リンク先でも説明されている通りモナドの実装的な感じで作られているので、別の例えば、ガード付きシーケンス: gseq { ... } 的なものも作ることができる)

例えば、
{2..4};;とかしてみれば
それだけでシーケンスが作れることが分かります。
それではと、
{yield 2;yield 3;yield 4};;
とかしてみると、
Sequence expressions should be of the form 'seq { ... }'.
Sequence expressions without a 'seq' prefix are deprecated

と怒られる(ウォーニング)ので、これ(seq を付けること)が構文的な使い方をされていると分かります。
プロフィール

T GYOUTEN

Author:T GYOUTEN
F#と英単語とフリーソフトと読書に興味があります。
ホームページでフリーソフトも公開しています。どぞ御贔屓に。

最新記事
最新コメント
最新トラックバック
月別アーカイブ
カテゴリ
フリーエリア
フリーエリア
blogram投票ボタン
検索フォーム
RSSリンクの表示
リンク
ブロとも申請フォーム

この人とブロともになる

QRコード
QRコード
上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。