検索
リンク
タグ
ASP.NET
.NET
ASP.NET MVC
F#
Visual Studio
Azure
ASP.NET Core
ライトニングトーク
Plone
Selenium
AJAX
C#
jQuery
SQL Server
ADO.NET Entity Framework
JavaScript
WebMatrix
EFCore
LINQ
Fizz-Buzz
カテゴリ
最新の記事
最新のコメント
記事ランキング
最新のトラックバック
以前の記事
2024年 03月 2024年 02月 2024年 01月 2023年 12月 2023年 11月 2023年 10月 2023年 09月 2023年 08月 2023年 07月 2023年 06月 2023年 05月 2023年 04月 2023年 03月 2023年 02月 2023年 01月 2022年 12月 2022年 11月 2022年 10月 2022年 09月 2022年 08月 2022年 07月 2022年 06月 2022年 05月 2022年 04月 2022年 03月 2022年 02月 2022年 01月 2021年 12月 2021年 11月 2021年 10月 2021年 09月 2021年 08月 2021年 07月 2021年 06月 2021年 05月 2021年 04月 2021年 03月 2021年 02月 2021年 01月 2020年 12月 2020年 11月 2020年 10月 2020年 09月 2020年 08月 2020年 07月 2020年 06月 2020年 05月 2020年 04月 2020年 03月 2020年 02月 2020年 01月 2019年 12月 2019年 11月 2019年 10月 2019年 09月 2019年 08月 2019年 07月 2019年 06月 2019年 05月 2019年 04月 2019年 03月 2019年 02月 2019年 01月 2018年 12月 2018年 11月 2018年 10月 2018年 09月 2018年 08月 2018年 07月 2018年 06月 2018年 05月 2018年 04月 2018年 03月 2018年 02月 2018年 01月 2017年 12月 2017年 11月 2017年 10月 2017年 09月 2017年 08月 2017年 07月 2017年 06月 2017年 05月 2017年 04月 2017年 02月 2017年 01月 2016年 12月 2016年 11月 2016年 10月 2016年 09月 2016年 08月 2016年 07月 2016年 06月 2016年 05月 2016年 04月 2016年 03月 2016年 02月 2016年 01月 2015年 12月 2015年 11月 2015年 10月 2015年 09月 2015年 08月 2015年 07月 2015年 05月 2015年 04月 2015年 03月 2015年 02月 2015年 01月 2014年 12月 2014年 11月 2014年 10月 2014年 09月 2014年 08月 2014年 06月 2014年 04月 2014年 03月 2014年 02月 2014年 01月 2013年 12月 2013年 10月 2013年 09月 2013年 08月 2013年 07月 2013年 06月 2013年 05月 2013年 04月 2013年 03月 2013年 02月 2013年 01月 2012年 12月 2012年 11月 2012年 10月 2012年 09月 2012年 08月 2012年 07月 2012年 06月 2012年 05月 2012年 04月 2012年 03月 2012年 02月 2012年 01月 2011年 12月 2011年 11月 2011年 10月 2011年 09月 2011年 08月 2011年 07月 2011年 06月 2011年 05月 2011年 04月 2011年 03月 2011年 02月 2011年 01月 2010年 12月 2010年 11月 2010年 10月 2010年 09月 2010年 08月 2010年 07月 2010年 06月 2010年 05月 2010年 04月 2010年 03月 2010年 02月 2010年 01月 2009年 12月 2009年 10月 2009年 09月 2009年 07月 2009年 06月 2009年 05月 2009年 04月 2009年 03月 2009年 02月 2009年 01月 2008年 12月 2008年 11月 2008年 10月 2008年 09月 2008年 08月 2008年 07月 2008年 06月 2008年 05月 2008年 04月 2008年 03月 2008年 02月 2008年 01月 2007年 12月 2007年 11月 2007年 04月 2007年 03月 2007年 02月 2007年 01月 2006年 11月 2006年 10月 2006年 09月 2006年 08月 2006年 07月 |
2010年 05月 01日
さて、F# でアクティブパターンの続きである。
前回で、普通のアクティブパターンから、パーシャルアクティブパターンにまで駒を進めた。 今回はさらにもう一歩進んで、パラメタライズド アクティブパターンに挑戦である。 いきなり感想から言うと、"パラメータ化された" アクティブパターンとは、関数型プログラミングにおける部分適用みたい。 2010/05/06 追記 パラメータ化されたアクティブパターンは、通常のアクティブパターンでも使えます。 http://devadjust.exblog.jp/11066386/ ということで、まず準備として、とある整数値の範囲にマッチするパーシャルアクティブパターンを書いてみよう。 >let (|Between2And4|_|) n = if 2 <= n && n <= 4 then Some(n) else None;; まぁ、これだけである。 引数 n が 2以上4以下ならマッチ、というわけだ。 普通に関数として呼び出してみると、 >(|Between2And4|_|) 3;; val it : int option = Some 3 >(|Between2And4|_|) 5;; val it : int option = None と、なるほど、たしかに期待どおりの挙動を示してくれる。 ということでパターンマッチのコードに組み上げてみる。 >let Test = fun x -> > match x with > |Between2And4 a -> printfn "%d is between 2 and 4." > |_ -> printfn "unmatch.";; 早速、関数 Test を呼び出してみる。 >Test 3;; 3 is between 2 and 4. val it : unit = () >Test 5;; unmatch. val it : unit = () ...と、まぁ、ここまでは前回と変わらない。 さて、パーシャルアクティブパターン (|Between2And4|_|) であるが、「2」と「4」というマジックナンバーが埋め込まれており、再利用性が悪い。 10以上100未満ならマッチするパーシャルアクティブパターンが欲しくなったら、また新たに (|Between10And100|_|) を書き起こすのか? イヤイヤあり得ないでしょ。 ということで "パラメタライズド" の出番なのである。 先ほどの (|Between2And4|_|) を、範囲の開始値と終了値を引数に受け取るように書き換える。 >let (|Between|_|) b e n = if b <= n && n <= e then Some(n) else None;; そしてパターンマッチの構文は次のようになる。 >let TestB = fun x -> > match x with > |Between 10 100 a -> printfn "%d is between 10 and 100." > |_ -> printfn "unmatch.";; つまり、上記、赤く表記した部分がアクティブパターンであり、「10」と「100」という "パラメータ" でアクティブパターンを "完成" させているわけだ。 この、「パラメータを与える」というあたりが、部分適用を想起させる。 なお、a は前回でも触れたとおり、引数 x がパターン Between にマッチした場合の Some(n) の n に束縛される。 これで、次のように機能する。 >TestB 11;; 11 is between 10 and 100. val it : unit = () >TestB 234;; unmatch. val it : unit = () 万々歳。 2010/05/06 追記 パラメータ化されたアクティブパターンは、以下に記載した記述とは少々異なりますが、通常のアクティブパターンでも使えます。 http://devadjust.exblog.jp/11066386/ ちなみに、パーシャルじゃない、普通のアクティブパターンに2つ以上の引数を付けて試してみた。 >let (|Between|NotBetween|) b e n = if b <= n && n <= e then Between else NotBetween; この定義自体は成功する。 関数として呼び出しても、たしかに機能する。 > (|Between|NotBetween|) 2 4 3;; val it : Choice しかし、下記のようにパターンマッチに組み込んでしまうと、 >let Test = fun x -> > match x with > |Between 2 4 -> printfn "%d is between 2 and 4." x > |NotBetween 2 4 -> printfn "%d is not between 2 and 4." x 下記のエラーに出くわすことになる。 error FS0722: Only active patterns returning exactly one result may accept arguments 以上。 ということで、やれやれ、随分苦労したけど、パラメタライズド アクティブパターンにまでこぎ着けたようだ。 次回はこれらを武器に、Fizz-Buzz 問題を変則的に解いてみようと思う。
by developer-adjust
| 2010-05-01 22:45
| .NET
|
Comments(2)
Commented
by
のぷひさ
at 2010-05-02 06:03
x
順調に進んでますね!
前回の記事の Option 型ですが、 Haskell に Maybe って型ありましたよね? data Maybe a = Nothing | Just a あれと同じようなものです。 F#で定義するならば、 type 'a Option = Some of 'a | None ;; という風になります。 'aは型変数です。 この型の値は、「Noneもしくは、何らかの値」になります。 たとえば、.NETの文字列検索メソッドIndexOfの戻り値は、見つからなかったら「-1」を返すことになっていますが、F#流に考えると、見つかった場合にSome index, なければNoneを返す、という風になります。 通常のアクティブパターンですが、以下のように書けたりもします。 > let (|Between|) x y n = x <= n && n <= y ;; > match 50 with | Between 40 60 false -> "fufufu!" | Between 10 20 true -> "hehehe!" | Between 20 80 true -> "hohoho!" | _ -> "hahaha!" ;; val it : string = "hohoho!" このようにした場合、関数の戻り値まで考慮してやります。 (true, falseとconstパターンでマッチさせています)
0
Commented
by
developer-adjust at 2010-05-06 12:42
返信が遅くなりましたが、コメントありがとうございます。
大変勉強になります。 なるほど、パラメタライズドアクティブパターンは必ずしもパーシャルアクティブパターンの専売特許ではなくて、戻り値も含めたパターンマッチを行うことで活きるのですね。 うっかり C# 脳になってました。 ところで、では、 > let (|Foo|Bar|) x y n = if ... then Foo else Bar;; というように、パラメタライズドの場合にも、Foo か Bar かを返すようなパターンで書けるのでしょうかね? パターンマッチのところで |Foo 10 20 Foo -> ... と書くわけにもいかないでしょうから、これは書けない(すなわち意味不明の構文となる)と思いました。 あとでちゃんと確かめておこうと思います。
|
ファン申請 |
||