Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Fluent Feature in F#

2,714 views

Published on

from OCaml Meeting 2010 in Nagoya

  • Be the first to comment

Fluent Feature in F#

  1. 1. F#の流技<br />Fluent Feature in F#<br />by いげ太<br />あいさつ。自己紹介。<br />
  2. 2. 本田△<br />流技といえば本田。無回転シュート。空気の流れを利用。大活躍!<br />ネットでよくこんなのを見た。「本田△」は前へ前へ攻めていく感じ?<br />じゃなく、本田△⇒本田三角形⇒本田さんかっけー⇒本田さんカッコイイ。<br />
  3. 3. OCaml△<br />ていうか、今日はOCaml Meetingなわけで。<br />OCamlさんかっけー。<br />って言いたかったけど、僕はWindowsしか知らないので。<br />
  4. 4. F# △<br />似た言語であるF#について話したい。F#は、かんたんにはOCaml.NETです。<br />ていうか。△似合わない? サッカーならいい。アゲアゲで、敵陣に攻めてる感じ。<br />プログラミング言語で、上って? ソース コードの上の方? それ後ろ向きじゃん。<br />
  5. 5. F#<br />前向きにいきましょう。矢印は未来を指してないと。<br />F#には横向きの三角、というか、矢印がよく似合います。<br />でもこれ、縦書き文字で無理やり横向きの三角を出してますので。<br />
  6. 6. F# |><br />こうしましょう。パイプと大なりであらわす。<br />この横向きの矢印は、F#ではパイプライン演算子と呼ばれます。<br />パイプライン演算子は、ライブラリ標準の演算子だったりします。<br />
  7. 7. パイプライン演算子 |><br />h (g (f x))<br />↓<br />x |> f |> g |> h<br />ネストいらずって<br />素敵やん!?<br />関数適用のネストをなくして見やすくする演算子。補助的な演算子。<br />前から順番に、xをfに適用して、その返り値をgに適用して、また<br />その返り値をhに適用して、その結果を得る。わかりやすい!<br />
  8. 8. パイプライン演算子?<br />let (|>) x f = f x<br />let wup n = 2 * n<br />let ans =2 |> wup |> wup |> wup<br />// valans : int = 16<br />(|>)は、前向きなパイプライン演算子、前方パイプ演算子。<br />定義はこんな風になっている。ちょっとした例も。ダブルアップで倍々ゲーム。<br />でもさ、若干だけど、重くなるんじゃない? 無駄じゃない、こんなの?<br />
  9. 9. パイプライン演算子!<br />let inline (|>) x f = f x<br />let wup n = 2 * n<br />let ans = 2 |> wup |> wup |> wup<br />// let ans = wup (wup (wup 2))<br />// valans : int = 16<br />(|>)は、実際にはインライン関数(演算子)として定義されています。<br />インライン展開されるので実行時のコストはゼロ。<br />気兼ねなく、存分に使ってください。乱用バッチコイ。<br />
  10. 10. 後ろから前から<br />h @@ g @@ f @@ x<br />h (g (f x))<br />x |> f |> g |> h<br />関数型の<br />語順<br />でもさ、関数型コードとの親和性で言えば@@の方がいいんでない?<br />
  11. 11. F#は.NET言語であり、当然OOPの機能を備える。<br />.NET使いも納得の思考の流れでコードが記述できる。<br />.NETといえばオブジェクト指向ですよ<br />h @@ g @@ f @@ x<br />x.F().G().H()<br />x |> f |> g |> h<br />OOPの<br />語順<br />
  12. 12. ところで、F#Teamの一人であるBrianMcNamaraが、<br />stackoverflowのとあるスレッドでこんなことを書いていました。<br />要は、ざっくり言うと、前方パイプ演算子は文化だ、と。<br />前方パイプ演算子は文化だ<br />Brian McNamara writes,<br />“I think (|>) is an important operatorin the F# ‘culture’.”<br />http://stackoverflow.com/questions/1457140/<br />
  13. 13. 文化ですってよ。<br />One more thing<br />One more thing...<br /><censored><br />
  14. 14. <censored><br />ドット記法の語順とあわせ打っただけをもって「文化」と言っているわけじゃあない。<br />だけじゃない<br />One more thing...<br />だけじゃない!!<br /><censored><br />
  15. 15. F#「OCamlと違うんです」<br />(* OCaml *)<br />let n = 2 + 3 (* 5 *)<br />let m = 2.0 +. 3.0 (* 5.0 *)<br />// F#<br />let n = 2 + 3  // 5<br />let m = 2.0 + 3.0  // 5.0<br />たとえば、.NETには演算子オーバーロードがある。<br />型推論の完全性を重んじるOCamlとは一線を画す。<br />
  16. 16. オーバーロードと型推論<br />let func1 x =<br />System.Console.WriteLine(x)// error FS0041<br /> x + 1<br />let func2 (x: int) =<br />System.Console.WriteLine(x)<br /> x + 1<br />let func3 x =<br /> let y = x + 1<br />System.Console.WriteLine(x)<br /> y<br />let func4 x =<br />printfn "%A" x<br /> x + 1<br />まあ割と型推論と相性が悪いのですけどもー。<br />型推論ってば、評価時の型環境すべてをひっくるめて見てくれる。<br />でも、オーバーロード解決は、その場その場で行われる。<br />
  17. 17. F#「.NETですから」<br />OCamlはStructural Subtyping<br />OCamlにはRow Polymorphismもある<br />F#はNominalSubtyping<br />.NET的に考えてNominalでなきゃマズイ<br />⇒ F#の型推論は残念!?<br />で、オブジェクト指向の方向性としても、こんな風に違うわけで。<br />ちょっと難しいので突っ込んで話はしませんが。<br />
  18. 18. デモ<br />> String.length "hoge";;<br />val it : int = 4<br />> "hoge".Length;;<br />val it : int = 4<br />> String.length;;<br />val it : (string -> int) = <fun:it@3><br />> (fun s -> s.Length);;<br /> (fun s -> s.Length);;<br /> ----------^^^^^^^^<br />stdin(4,11): error FS0072: このプログラムの場所の前方にある情報に基づく不確定の型のオブジェクトに対する参照です。場合によっては、オブジェクトの型を制約する型の注釈がこのプログラムの場所の前に必要です。この操作で参照が解決される可能性があります。<br />> (fun (s: string) -> s.Length);;<br />val it : string -> int = <fun:clo@5><br />とりあえず、OCaml的に考えて、どんなふうに残念かってーのをデモで見ます。<br />ドット記法で書かれたオブジェクトの型は推論されない!<br />型注釈に頼らざるを得ない。<br />
  19. 19. デモ<br />> let intLength n =<br />- (fun (s: string) -> s.Length)<br />- ( (fun n -> n.ToString()) n );;<br />valintLength : 'a -> int<br />> let intLength n =<br />- (fun (s: string) -> s.Length)<br />- ( (fun (n: int) -> n.ToString()) n );;<br />valintLength : int -> int<br />> let intLength (n: int) =<br />- n |> (fun n -> n.ToString()) |> (fun s -> s.Length);;<br />valintLength : int -> int<br />ちょっと意図的な例。それぞれの引数に型注釈付けるのは煩雑極まりない。<br />なんとかならない? それまでに型が決まればいい。F#の型決定は左から右。<br />なので、前方パイプ演算子を使えば、残念さをすこしはカバーできるかも!?<br />
  20. 20. まとめ<br />> F#<br />- |> 関数型ベース<br />- |> .NET言語ですが何か<br />- |>OOPは必須です<br />- |> Nominalだし型注釈を免れない<br /><ul><li> |> 型推論を最大限活かしたい
  21. 21. ;;</li></ul>val it : culture = だまって前方パイプ書けよ<br />
  22. 22. More Feature<br />単位系-> 数値に単位を付けて計算<br />アクティブ パターン -> パターンとして使用できる関数<br />オブジェクト式 -> 無名クラス<br />コンピュテーション式 -> モナド<br />イベント ドリブン -> リアクティブに記述可能<br />非同期実行 -> 非同期ワークフロー、アクター<br />他にもおもしろいのいっぱいあるよー。<br />
  23. 23. Reserved as Keywordsfor future expansion<br />http://msdn.microsoft.com/en-us/library/dd233249.aspx<br />わくわくどきどきの将来の機能拡張のための予約語。<br />
  24. 24. F#<br />F is for Fun!<br />ありがとうございました。<br />

×