スポンサーサイト

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

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

今回のお題は「Computation Expression(14) the state workflow(4)」です
 
前回でstate workflowの基本部品を紹介しましたが、今回必要となる部分だけを、もう一度ここで再掲します。
 
type StateFunc<'state,'a> = StateFunc of ('state -> 'a * 'state)
 
//StateFuncを関数としてsに作用させる
let Run (StateFunc f) s = f s
 
type StateBuilder () =
    //このBindの定義がState workflowのキモ
    member this.Bind(stfunc,rest) = 
        StateFunc(fun old_s ->
                let v,new_s = Run stfunc old_s
                Run (rest v) new_s
             )                         
 
    member this.Return (x:'a) =
            StateFunc(fun s -> x,s) 
 
 
 
//stateをそのまま値とstateにセットする(StateFunc型のオブジェクトを返す)
let GetState = StateFunc ( fun s -> (s,s))
 
//stateを引数にして、(何でも->((),state)というStateFunc型のオブジェクトを返す
let SetState s = StateFunc (fun _ -> ((),s))
 
ここまででStateBuilderクラスのBindとRetrunしか定義していませんでした。今回はこれ以外の部分を定義したいと思います。
 
    member this.Combine(p1:StateFunc<'s,unit>,p2:StateFunc<'s,'a>)=
            StateFunc(fun s ->
                let (),ns = Run p1 s
                Run p2 ns
            )
 
    member this.Delay(rest :unit -> StateFunc<'s,'a>)=
            StateFunc(fun s -> Run(rest()) s)
 
    member this.For(eles : seq<'a> , body : ('a -> StateFunc<'s,unit>))=
        StateFunc(fun s ->
                    let refs = ref s
                    for e in eles do
                        let (),ns = Run (body e) (!refs)
                        refs := ns 
                    (),!refs
                   )  
 
 
    member this.While(pd:unit -> bool,body:StateFunc<'s,unit>)=
            StateFunc(fun s ->
                let refs =ref s
                while pd() = true do
                    let (),ns = Run body (!refs)
                    refs := ns
                (),!refs
            )
 
    member this.Using<'a,'s,'b when 'a :> IDisposable>
                                     (x:'a,rest:'a -> StateFunc<'s,'b>)=
        StateFunc(fun s->
            try
                Run(rest x) s
            finally
                x.Dispose()
        )        
 
    member this.TryFinally(tryBlock:StateFunc<'s,'a>,finallyBlock :unit->unit)=
        StateFunc(fun s ->
            try
                Run tryBlock s
            finally
                finallyBlock()
        )    
 
    member this.TryWith(tryBlock:StateFunc<'s,'a>,exnHandler:exn ->StateFunc<'s,'a>)=
        StateFunc(fun s ->
                   try
                        Run tryBlock s
                    with
                    | e -> Run (exnHandler e) s 
                  )   
 
    member this.Zero() =
        StateFunc(fun s -> (),s)
 
それでは前回(去年の話になりますが)作った電卓にfor,whileを使ってみます。
 
let state = StateBuilder() 
 
let pushButton k kind = 
    state {let! c_val,history = GetState  
           do! SetState((c_val + k, "push" + kind :: history)) 
           } 
 
let pushButtonA = 
    pushButton 1 "A" 
     
let pushButtonB = 
    pushButton 10 "B" 
 
let pushButtonC = 
    pushButton 100 "C" 
 
let pushButtonSample = 
    state{  
            for i = 0 to 4 do
                do! pushButtonA 
            
            let k = ref 0
            while !k < 3 do
                do! pushButtonB
                k := !k + 1 
            do! pushButtonC 
            } 
 
としておいて、
 
> Run pushButtonSample (0,[]) ;; 
 
とすると
 
val it : unit * (int * string list) =
  (null,
   (135,
    ["pushC"; "pushB"; "pushB"; "pushB"; "pushA"; "pushA"; "pushA"; "pushA";
     "pushA"]))
 
ということで皆様、あけましておめでとうございます。(遅い!)
スポンサーサイト

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

コメントの投稿

非公開コメント

プロフィール

T GYOUTEN

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

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

この人とブロともになる

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