Your SlideShare is downloading. ×
0
Monadicプログラミング マニアックス
Monadicプログラミング マニアックス
Monadicプログラミング マニアックス
Monadicプログラミング マニアックス
Monadicプログラミング マニアックス
Monadicプログラミング マニアックス
Monadicプログラミング マニアックス
Monadicプログラミング マニアックス
Monadicプログラミング マニアックス
Monadicプログラミング マニアックス
Monadicプログラミング マニアックス
Monadicプログラミング マニアックス
Monadicプログラミング マニアックス
Monadicプログラミング マニアックス
Monadicプログラミング マニアックス
Monadicプログラミング マニアックス
Monadicプログラミング マニアックス
Monadicプログラミング マニアックス
Monadicプログラミング マニアックス
Monadicプログラミング マニアックス
Monadicプログラミング マニアックス
Monadicプログラミング マニアックス
Monadicプログラミング マニアックス
Monadicプログラミング マニアックス
Monadicプログラミング マニアックス
Monadicプログラミング マニアックス
Monadicプログラミング マニアックス
Monadicプログラミング マニアックス
Monadicプログラミング マニアックス
Monadicプログラミング マニアックス
Monadicプログラミング マニアックス
Monadicプログラミング マニアックス
Monadicプログラミング マニアックス
Monadicプログラミング マニアックス
Monadicプログラミング マニアックス
Monadicプログラミング マニアックス
Monadicプログラミング マニアックス
Upcoming SlideShare
Loading in...5
×

Thanks for flagging this SlideShare!

Oops! An error has occurred.

×
Saving this for later? Get the SlideShare app to save on your phone or tablet. Read anywhere, anytime – even offline.
Text the download link to your phone
Standard text messaging rates apply

Monadicプログラミング マニアックス

2,264

Published on

クラウド温泉3.0の資料です。

クラウド温泉3.0の資料です。

Published in: Technology
0 Comments
4 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total Views
2,264
On Slideshare
0
From Embeds
0
Number of Embeds
3
Actions
Shares
0
Downloads
15
Comments
0
Likes
4
Embeds 0
No embeds

Report content
Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
No notes for slide

Transcript

  • 1. Monadicプログラミングマニアックス2012年年8⽉月18⽇日浅海智晴
  • 2. 活動
  • 3. 関連サイト•  Modegramming Style (テキストDSL駆動開発を テーマにしたブログ) •  http://modegramming.blogspot.com/•  SimpleModeler •  http://github.com/asami/simplemodeler/•  SmartDox •  http://github.com/asami/smartdox•  g3フレームワーク •  http://code.google.com/p/goldenport3/•  g4フレームワーク •  http://github.com/asami/goldenport-android- library/
  • 4. ⽂文脈
  • 5. アジェンダMonadicプログラミングでやりたいこと 関数型プログラミング Monadicプログラミング
  • 6. 関連記事•  Modegramming Style •  http://modegramming.blogspot.jp/•  クラウド温泉3.0@⼩小樽〜~   クラウド温泉3.0 (18) / Promise
  • 7. 諸元•  スライド •  Scala 2.9.2 •  Scalaz 6.0.4•  最新 •  Scala 2.10.0 M6 •  Scalaz 7 開発中 (2012年年4⽉月リリース予定?)•  Scala 2.10で並列列プログラミング周りが⼤大幅に変更更され る予定 •  Akka(Actor)、STM、Future/Promise •  Scala 2.10 + Scalaz7で新しいバランスになるので、⾒見見極 めが必要
  • 8. 新しい現実ハードウェア•  メニーコア、⼤大容量量メモリ、SSD•  インメモリデータベース•  並列列プログラミングクラウド・プラットフォーム•  クラウド・サービス、スマート・デバイス•  故障、遅延•  ⼤大規模データ、⼤大規模演算•  ⾼高頻度度イベント•  ⾮非同期、並列列、分散•  NoSQL
  • 9. アプリケーションの階層と役割アプリケー •  DSLの作法に従ってビジネスロ ジックを記述 ション •  OO、関数型のスキルは最低限 •  フレームワークを簡単に使⽤用する DSL ための専⽤用⾔言語 •  OO、関数型の⾼高度度なスキルフレーム •  ドメインの共通処理理を記述 ワーク •  OO、関数型の⾼高度度なスキル
  • 10. ⽤用語•  セッション内でのローカルな⽤用法•  (普通の)オブジェクト指向⾔言語 •  Java的なオブジェクト指向⾔言語。オブジェクト+クラス+ 抽象データ型+静的型付け+⼿手続き+値。•  本物のオブジェクト指向⾔言語 •  オブジェクトとメッセージから構成される核に何かを加え たもの。•  関数型⾔言語 •  純粋関数型⾔言語(での利利⽤用も可能) •  イミュータブル、参照透過性 •  モナドが⼀一級市⺠民 •  型クラス(相当)
  • 11. Monadicプログラミングでやりたいこと
  • 12. Monadicプログラミングでやりたいこと•  定義 •  普通 •  Monadを使ったプログラミング。 •  本セッションでの広い意味 •  Monadを中⼼心としつつも、旧来からあるFunctorによるプログ ラミング、関数合成、コンビネータなども包含しつつ、パイプ ライン・プログラミングのスタイルとしてまとめたもの。•  やりたいこと •  楽々プログラミング •  並列列プログラミング •  DSL
  • 13. 楽々プログラミングdef main(args: Array[String]) { records |> build部⾨門  >>> buildTree >>> showTree }def build部⾨門(records: Seq[Map[Symbol, Any]]): Map[Int, 部⾨門] = { records.foldRight(Map[Int, 部⾨門]())((x, a) => { val 部⾨門ID = x(部⾨門ID).asInstanceOf[Int] val 部⾨門名  = x(部⾨門名).asInstanceOf[String] val 親部⾨門ID = x(親部⾨門ID).asInstanceOf[Option[Int]] val 親部⾨門名  = x.get(親部⾨門名).asInstanceOf[Option[String]] a + (部⾨門ID -> 部⾨門(部⾨門ID, 部⾨門名, 親部⾨門ID, 親部⾨門名)) })}def buildTree(sections: Map[Int, 部⾨門]): Tree[部⾨門] = { def build(sec: 部⾨門): Tree[部⾨門] = { val children = sections collect { case (k, v) if v.親部⾨門ID == sec.部⾨門ID.some => v } node(sec, children.toStream.sortBy(_.部⾨門ID).map(build)) } build(sections(1))}def showTree(tree: Tree[部⾨門]) { println(tree.drawTree(showA[部⾨門]))}
  • 14.  val records = List(Map(部⾨門ID -> 1, 部⾨門名  -> "営業統括", Map(部⾨門ID -> 121, 親部⾨門ID -> None, 部⾨門名  -> "近畿⽀支店", 親部⾨門名  -> None), 親部⾨門ID -> Some(12), Map(部⾨門ID -> 11, 親部⾨門名  -> "⻄西⽇日本統括"), 部⾨門名  -> "東⽇日本統括", Map(部⾨門ID -> 122, 親部⾨門ID -> Some(1), 部⾨門名  -> "中国⽀支店", 親部⾨門名  -> "営業統括"), 親部⾨門ID -> Some(12), Map(部⾨門ID -> 12, 親部⾨門名  -> "⻄西⽇日本統括"), 部⾨門名  -> "⻄西⽇日本統括", Map(部⾨門ID -> 123, 親部⾨門ID -> Some(1), 部⾨門名  -> "四国⽀支店", 親部⾨門名  -> "営業統括"), 親部⾨門ID -> Some(12), Map(部⾨門ID -> 13, 親部⾨門名  -> "⻄西⽇日本統括"), 部⾨門名  -> "⾸首都圏統括", Map(部⾨門ID -> 124, 親部⾨門ID -> Some(1), 部⾨門名  -> "九州⽀支店", 親部⾨門名  -> "営業統括"), 親部⾨門ID -> Some(12), Map(部⾨門ID -> 111, 親部⾨門名  -> "⻄西⽇日本統括"), 部⾨門名  -> "北北海道⽀支店", Map(部⾨門ID -> 125, 親部⾨門ID -> Some(11), 部⾨門名  -> "沖縄⽀支店", 親部⾨門名  -> "東⽇日本統括"), 親部⾨門ID -> Some(12), Map(部⾨門ID -> 112, 親部⾨門名  -> "⻄西⽇日本統括"), 部⾨門名  -> "東北北⽀支店", Map(部⾨門ID -> 131, 親部⾨門ID -> Some(11), 部⾨門名  -> "東京⽀支店", 親部⾨門名  -> "東⽇日本統括"), 親部⾨門ID -> Some(13), Map(部⾨門ID -> 113, 親部⾨門名  -> "⾸首都圏統括"), 部⾨門名  -> "北北陸陸⽀支店", Map(部⾨門ID -> 132, 親部⾨門ID -> Some(11), 部⾨門名  -> "北北関東⽀支店", 親部⾨門名  -> "東⽇日本統括"), 親部⾨門ID -> Some(13), Map(部⾨門ID -> 114, 親部⾨門名  -> "⾸首都圏統括"), 部⾨門名  -> "中部⽀支店", Map(部⾨門ID -> 133, 親部⾨門ID -> Some(11), 部⾨門名  -> "南関東⽀支店", 親部⾨門名  -> "東⽇日本統括"), 親部⾨門ID -> Some(13), 親部⾨門名  -> "⾸首都圏統括"))
  • 15. 部⾨門(1,営業統括,None,Some(None))|+- 部⾨門(11,東⽇日本統括,Some(1),Some(営業統括))| || +- 部⾨門(111,北北海道⽀支店,Some(11),Some(東⽇日本統括))| || +- 部⾨門(112,東北北⽀支店,Some(11),Some(東⽇日本統括))| || +- 部⾨門(113,北北陸陸⽀支店,Some(11),Some(東⽇日本統括))| || `- 部⾨門(114,中部⽀支店,Some(11),Some(東⽇日本統括))|+- 部⾨門(12,⻄西⽇日本統括,Some(1),Some(営業統括))| || +- 部⾨門(121,近畿⽀支店,Some(12),Some(⻄西⽇日本統括))| || +- 部⾨門(122,中国⽀支店,Some(12),Some(⻄西⽇日本統括))| || +- 部⾨門(123,四国⽀支店,Some(12),Some(⻄西⽇日本統括))| || +- 部⾨門(124,九州⽀支店,Some(12),Some(⻄西⽇日本統括))| || `- 部⾨門(125,沖縄⽀支店,Some(12),Some(⻄西⽇日本統括))|`- 部⾨門(13,⾸首都圏統括,Some(1),Some(営業統括)) | +- 部⾨門(131,東京⽀支店,Some(13),Some(⾸首都圏統括)) | +- 部⾨門(132,北北関東⽀支店,Some(13),Some(⾸首都圏統括)) | `- 部⾨門(133,南関東⽀支店,Some(13),Some(⾸首都圏統括))
  • 16. 並列列プログラミング 準備 時間を測る関数 テスト関数def go[T](a: => T): (T, Long) = { val start = System.currentTimeMillis val f = (x: Int) => { val r = a Thread.sleep(x * 100) val end = System.currentTimeMillis x (r, end - start) }}scala> go(f(10)) scala> go {res176: (Int, Long) = (10,1000) | f(10) |} res253: (Int, Long) = (10,1001)
  • 17. PromiseのKleisliscala> val fp = f.promisefp: scalaz.Kleisli[scalaz.concurrent.Promise,Int,Int] =scalaz.Kleislis$$anon$1@9edaab8 Applicativescala> go((fp(1) |@| fp(2) |@| fp(3))(_ + _ + _).get)res215: (Int, Long) = (6,302) scala> go(f(1) + f(2) + f(3)) res212: (Int, Long) = (6,603) scala> go((1.some |@| 2.some |@| 3.some)(_ + _ + _).get) res237: (Int, Long) = (6,1)
  • 18. scala> go(List(1, 2, 3).map(fp).map(_.flatMap(fp)).sequence.get)res220: (List[Int], Long) = (List(1, 2, 3),602) scala> go(List(1, 2, 3).map(f).map(f)) res221: (List[Int], Long) = (List(1, 2, 3),1205) テスト関数 val fx = (x: Int) => { val t = math.abs(x - 4) Thread.sleep(t * 100) x } val fxp = fx.promise
  • 19. scala> go(List(1, 2, 3).map(fp).map(_.flatMap(fxp)).sequence.get)res222: (List[Int], Long) = (List(1, 2, 3),402) scala> go(List(1, 2, 3).map(f).map(fx)) res223: (List[Int], Long) = (List(1, 2, 3),1205)scala> go(List(1, 2, 3).map(fp >=> fxp).sequence.get)res230: (List[Int], Long) = (List(1, 2, 3),402) scala> go(List(1, 2, 3).map(f >>> fx)) res232: (List[Int], Long) = (List(1, 2, 3),1205)
  • 20. DSLimport org.goldenport.dataflow._val z = for (i <- table(T⽣生産実績)) yield { val x = i.sum(原価) + 10 val y = i.masterJoin(M部⾨門)((x, y) => x(部⾨門Id) == y(部⾨門Id) and x(製品Id) == y(製品Id)) val z = y.update(NEW_GENKA, x) val zz = z.where(x => x(部⾨門Id) == 1) val zzz = zz.record(SymbolFieldDef(A), SymbolFieldDef(B)) zzz}println(”SQL = " + z.toSql.toText)SQL = select sum(原価) + 10 as NEW_GENKA, A, Bfrom T⽣生産実績left outer join M部⾨門  on (T⽣生産実績.部⾨門Id = M部⾨門.部⾨門Id) and (T⽣生産実績.製品Id = M部⾨門.製品Id)Where T⽣生産実績.部⾨門Id = 1
  • 21. 関数型プログラミング
  • 22. 代数的データ型 •  Algebraic data type •  直積の直和の総和 •  再帰構造ケースクラスで直積を実現case class Person(name: String, age: Int)Case class Company(name: String, phone: String)Eitherで直積の直和を実現Either[Person, Company]sealedトレイトで直積の直和の総和を実現sealed trait Partycase class Person(name: String, age: Int) extends Partycase class Company(name: String, phone: String) extends Party
  • 23. 永続データ構造•  Persistent data structure•  変更更される際に変更更前のバージョンを常に保持するデータ構造で ある。このようなデータ構造は、更更新の際に元のデータ構造を書 き換えるのではなく、新たなデータ構造を⽣生成すると考えられ、 イミュータブルなデータ構造の構築に利利⽤用可能である(Wikipedia)
  • 24. 代数的構造デザインパターン結合律律 (associative law)•  半群 (semigroup)•  モノイド  (monoid) (a + b) + c = a + (b + c)•  群 (group)可換律律 (commutative law)•  可換半群•  可換モノイド a+b=b+a•  可換群(アーベル群)分配律律 (distributive law)•  環  (ring)•  体 (field) a * (b + c) = a * b + a * c
  • 25. 圏論論デザインパターン 圏  (category) モナド   • Hask圏 (Scala圏?) (monad) • クライスリ圏   (kleisli category) Applicative 射 (arrow, functor morphism) 関⼿手   (functor)
  • 26. 並列列プログラミング•  マルチスレッド   •  共有状態 (shared mutability) •  共有状態をロック ← 伝統的⽅方法 •  STM (Software Transactional Memory)•  アクター •  状態をアクターローカル(スレッドローカル)にする (isolating mutability) •  不不変オブジェクトによるメッセージで通信•  関数プログラミング⽅方式 •  代数的データ型、永続データ構造 •  ⇒ 参照透過性、不不変オブジェクト •  状態変更更ではなく、状態変更更命令令書を計算 •  イメージとしてはSQLの⽂文字列列を計算して作成する感じ •  モナドのメカニズムを使って並列列処理理(+状態変更更命令令書)を 隠蔽
  • 27. トピックス•  Monad •  http://modegramming.blogspot.jp/2012/08/30-13- monad.html•  Monoid •  http://modegramming.blogspot.jp/2012/08/30-12- monoid.html•  Fold •  http://modegramming.blogspot.jp/2012/07/30-10- map-filter-fold.html
  • 28. Monadicプログラミングの効⽤用 Java⾵風def validate(name: String, age: Int): ValidationNEL[Throwable, (String,Int)] = {! val a = validateName(name) ! val b = validateAge(age) ! if (a.isSuccess && b.isSuccess) { ! val a1 = a.asInstanceOf[Success[NonEmptyList[Throwable], String]].a ! val b1 = b.asInstanceOf[Success[NonEmptyList[Throwable], Int]].a ! Success((a1, b1)) ! } else if (a.isSuccess) { ! b.asInstanceOf[Failure[NonEmptyList[Throwable], (String, Int)]] ! } else if (b.isSuccess) { ! a.asInstanceOf[Failure[NonEmptyList[Throwable], (String, Int)]] ! } else { ! val a1 = a.asInstanceOf[Failure[NonEmptyList[Throwable], String]].e ! val b1 = b.asInstanceOf[Failure[NonEmptyList[Throwable], Int]].e ! Failure(a1 |+| b1) ! } !}!
  • 29. Scala (関数型プログラミング)def validate(name: String, age: Int):ValidationNEL[Throwable, (String, Int)] = { ! validateName(name) match { ! case Success(a) => validateAge(age) match { ! case Success(b) => Success((a, b)) ! case Failure(e) => Failure(e) ! } ! case Failure(e1) => validateAge(age) match { ! case Success(b) => Failure(e1) ! case Failure(e2) => Failure(e1 |+| e2) ! } ! } !} !Scalaz (Monadicプログラミング)def validate(name: String, age: Int):ValidationNEL[Throwable, (String, Int)] = { ! (validateName(name) ⊛ validateAge(age))((_, _)) !}!URL: http://modegramming.blogspot.jp/2012/04/ scala-tips-validation-10-applicative.html
  • 30. Monadicプログラミング
  • 31. Arrowを⽤用いたデーターフロー
  • 32. 関数合成
  • 33. モナドによる計算⽂文脈 (1)
  • 34. モナドによる計算⽂文脈 (2)
  • 35. パイプラインの構成部品メソッド メソッド動作 動作イメージ コンテナ型 要素型 要素数map コンテナ内の要素に M[A]→M[B] 変わらない 変わる 同じ 関数を適⽤用して新し いコンテナに詰め直 す。filter コンテナ内の要素を M[A]→M[A] 変わらない 変わらない 同じ/減る 選別して新しコンテ ナに詰め直す。fold コンテナをまるごと M[A]→N 変わる N/A N/A 別のオブジェクトに 変換する。reduce コンテナの内容を⼀一 M[A]→A 変わる N/A N/A つにまとめる。collect コンテナ内の要素に M[A]→M[B] 変わらない 変わる 同じ/減る 部分関数を適⽤用して 選択と変換を⾏行行う。flatMap コンテナ内の要素ご M[A]→M[B] 変わらない 変わる 同じ/増える/減 とにコンテナを作成 る する関数を適⽤用し最 後に⼀一つのコンテナ にまとめる。
  • 36. まとめ•  Monadicプログラミングの狙い •  楽々プログラミング •  並列列プログラミング •  DSL •  データフロー•  関数型プログラミング •  ⼀一昔前の関数型プログラミングとは別物 •  A→B、A→M[B]の関数が基本 •  モナド、モノイド •  型クラス•  Monadicプログラミング •  パイプラインで考えると関数型にアプローチしやすい •  データフローで業務モデルと繋げたい
  • 37. END

×