工事中
工事中
工事中
工事中
パーシャルアクティブパターンは、マッチの失敗を検出できるアクティブパターンです
パーシャルアクティブパターンを使うには、下記の必要があります。
では、さっそく具体的なサンプルを示します。
下記のサンプルは、ユーザーのアクセスレベルを調べます。
#light type AccessLevel = High | Low let (|AdminUser|_|) name = if name = "admin" then Some(High) else None let (|GuestUser|_|) name = if name = "guest" then Some(Low) else None let CheckAccessLevel n = match n with | AdminUser n -> "Access Level High" | GuestUser n -> "Access Level Low" | _ -> "Access Deny" let ret1 = CheckAccessLevel "admin" printfn "admin : %s" ret1 let ret2 = CheckAccessLevel "guest" printfn "guest : %s" ret2 let ret3 = CheckAccessLevel "yamada" printfn "yamada : %s" ret3
実行結果
admin : Access Level High guest : Access Level Low yamada : Access Deny
書いてみたものの、ちょっと微妙なサンプルですねw 良いサンプルが思いついたらそれを掲載するようにします。
とりあえず、アクティブパターンの書き方はこのサンプルでもわかっていただけたかと思います。
工事中
ワークフローはworkflowとbuilderからの2つからなります。
■workflow
workflowはcomputation expressionとも呼ばれます。
・workflow(computation expression)の書式
ident { cexpr }
※identには任意の名前をつけることができる。
workflow{ let x = 2 let! y = 3 return x*y }
実はworkflowは継続的渡し処理の糖衣構文で、let! や returnはそれを実現するためのキーワードです。 先ほど定義されたworkflowは構文糖衣なしで下記のようになります。
workflow.Delay(fun () -> workflow.Let(2, (fun a -> workflow.Bind(3, fun b -> workflow.Return(a * b ) ) ) ) ) )
workflowは上記のように解釈されて実行されます。 糖衣構文でない例を見ると継続的に次へ渡しながら処理していくworkflowの特徴がよくわかるのではないでしょうか。
糖衣構文と糖衣なし構文の対応は下記になっています。
let! | Bind |
let | Let |
return | Return |
※他にもあるので、情報整理して追加します。。
■builder
workflowを構築するオブジェクトです。 letやlet!などの動作を定義します。 キーワードと糖衣なしのメソッドの対応は先ほどの表を参考にしてください。
#light type Workflow<'a> = (unit -> 'a ) let runWorkflow (a:Workflow<'a>) = a() let delay f = fun () -> runWorkflow ( f() ) type WorkflowBuilder() = // return member b.Return(x) = fun () -> x // let member b.Let(p,rest) : Workflow<'a> = rest p // let! member b.Bind(p,rest) : Workflow<'a> = rest p // delay member b.Delay(f) = delay f
では、ワークフローを実行してみましょう。
let workflow = new WorkflowBuilder() let num = workflow { let x = 2 let! y = 3 return x*y } let ret = runWorkflow num printfn "ret=%d" ret
sequence expressionはseqに関するworkflowです。
sequence expressionを利用することで、seq型をforやwhileなどの式から生成できます。
・sequence expressionの書式
seq { cexpr }
> seq { for i in 0 .. 3 -> i*i };; val it : seq= seq [0; 1; 4; 9]
リストや配列も同じような方法で生成できます。
・リスト
> [ for i in 0 .. 3 -> i*i ];; val it : int list = [0; 1; 4; 9]
・配列
> [| for i in 0 .. 3 -> i*i |];; val it : int array = [|0; 1; 4; 9|]
yield キーワードを利用すると、コレクションに値を追加して、計算を継続することができます。
名簿ファイル(name_list.txt)から名前を読み込んで、表示するプログラムを作成してみます。 seq型のreader に名前を追加していき、最後Seq.iterで一つずつ出力します。
・name_list.txtの内容
山田 中村 田中 鈴木
・サンプルコード
#light open System.IO let reader = seq { use reader = new StreamReader(File.OpenRead("name_list.txt")) while not reader.EndOfStream do yield reader.ReadLine() } Seq.iter ( printfn "%s" ) reader
・出力
山田 中村 田中 鈴木