スポンサーサイト

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

F#入門中級編第8回(Computation Expression(8))

今回はmember.Forを紹介します。
 
for文は
 
for pat in seq<'a> do cexpr    
 
の形ですが、これは
 
b.For(seq<'a>,(fun pat -> ≪cexpr≫))  //#1
 
の形に解釈されます。
 
ただ、実際にb.Forを自分で実装する場合は、「seq型のものから要素を取り出すことを試して、取り出せれば、何らかの作業をする」という操作の繰り返しを実装することになります。
またforの部分とその後の部分の連結の為にmember Combineの実装も必要です。
 
それでは、例を見てください。
 
open System.Collections.Generic
type ForBuilder01 () =
   member this.Bind(x,rest) = 
      rest x      
   member this.Return (x) = 
      x
   member this.Delay f = 
     f ()
   member this.Combine(a,b) =
     a
     b
   member this.Zero()  =
     ()
   member this.For (inp:seq<_>, f) =
    let rec loop(en:IEnumerator<_>)=
        if not(en.MoveNext()) then //終端まで来て要素が取り出せない場合
            this.Zero() 
        else
            printfn "%Aに関数を適用します" en.Current 
            f(en.Current)
            loop(en)
    loop(inp.GetEnumerator())
 
let forBld01 = new ForBuilder01()
 
let ForSample01 =
            forBld01{
                let sum = ref 0
                for i in [|1;2;3;4|] do
                   printfn "%A" i 
                   sum := !sum + i
                return (!sum)
                } 
                

1に関数を適用します
1
2に関数を適用します
2
3に関数を適用します
3
4に関数を適用します
4
 
val ForSample01 : int = 10
 
これを解釈した状態で、ForSample011という名前で定義すると次のようになります。
 
let ForSample011 =
    forBld01.Delay(fun ()->
        forBld01.Bind((ref 0),fun sum ->
            forBld01.Combine(
                forBld01.For([|1;2;3;4|],(fun i -> printfn"%A" i;sum := !sum + i)),
                forBld01.Delay(fun () -> forBld01.Return(!sum))))) 
                
 ((注)Letを使うとエラーがでるのでBindで代用しています。)
 
 実行結果は上と同じになります。
 
 Forの型はFor : seq<'a> * ('a -> M<'b>) -> M<'b>  となります。
 
さてここで宿題です。 
次をF#Interactiveで実行すると,ForSample02はどのように評価されるでしょうか。
 
type ForBuilder02 () =
   let rArr = new ResizeArray<int> ()
 
   member this.Bind(x,rest) = 
     rArr.Add(x)
     rest x       
   
   member this.Return (x) = 
     (x,rArr)
   
   member this.Delay f = 
     f ()
   
   member this.Combine(a,b) =
     a 
     b 
   
   member this.Zero()  =
     ()
   
   member this.For (inp:seq<_>, f) =
    let rec loop(en:IEnumerator<_>)=
        if not(en.MoveNext()) then 
            this.Zero() 
        else
            f(en.Current)
            rArr.Add(en.Current)
            loop(en)
    loop(inp.GetEnumerator())
 
let forBld02 = new ForBuilder02()
 
let ForSample02 =
    let prt (x:int) = printfn "seq内の%Aを追加" x
    forBld02{
        let! x = 7
        for i in [|6;5|] do 
             prt i
        return (x) 
        }
 
スポンサーサイト

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

コメントの投稿

非公開コメント

プロフィール

T GYOUTEN

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

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

この人とブロともになる

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