• Like
Scalaz effects
Upcoming SlideShare
Loading in...5
×

Thanks for flagging this SlideShare!

Oops! An error has occurred.

Published

 

  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Be the first to comment
No Downloads

Views

Total Views
4,833
On SlideShare
0
From Embeds
0
Number of Embeds
7

Actions

Shares
Downloads
9
Comments
0
Likes
2

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. Scalaz.effects使い方など、簡単に説明します よしだ(@halcat0x15a)
  • 2. scalaz.effectsとは● IOモナドやSTモナドなど、Haskellライクな入出力や可 変状態を扱うパッケージ。 ● package object effectsに関数やimplicitが定義され ているので、それをimportすることでIOモナドやSTモ ナドが使える。● Haskellの関数に対応しているので、"haskell 関数 名"でググればだいたい出てくる。
  • 3. IOについて● IO[A]は値であり、アクションといわれる。● 関数はアクションを返すだけで、実行はしない。● unsafePerformIOが呼ばれてはじめて実行される。● 実行後、型Aの結果が返る。 
  • 4. 主な標準入出力関数● def putChar (c: Char): IO[Unit]● def putStr (s: String): IO[Unit]● def putStrLn (s: String): IO[Unit]● def putOut [A] (a: A): IO[Unit]● def getChar : IO[Char]● def readLn : IO[String]
  • 5. 主なIO[A]の主なメソッド● def flatMap [B] (f: (A) ⇒ IO[B]): IO[B]● def map [B] (f: (A) ⇒ B): IO[B]● def bracket [B, C] (after: (A) ⇒ IO[B])(during: (A) ⇒ IO[C]): IO[C] ○ このメソッドはduringを適用したあと、afterを呼びます。 ○ afterは例外に関係なく呼ばれます。 ● def catchLeft : IO[Either[Throwable, A]]● def except (handler: (Throwable) ⇒ IO[A]): IO[A]● def unsafePerformIO : A ○ アクションを実行し、値を返します。
  • 6. 標準入出力関数の使い方import scalaz._import effects._import Scalaz._val i = for { _ <- putStrLn("Greetings! What is your name?") // 文字列を出力  inpStr <- readLn // 一行読み込む  outStr = "Welcome to Scalaz, " |+| inpStr |+| "!" // 新しい文字列を作る  _ <- putStrLn(outStr) // 作った文字列を出力} yield () // 戻り値はUniti.unsafePerformIO // ここで実行
  • 7. 結果scala> :load io.scalaLoading io.scala...import scalaz._import effects._import Scalaz._i: scalaz.effects.IO[Unit] = scalaz.effects.IO$$anon$2@10f436Greetings! What is your name?SanshiroWelcome to Scalaz, Sanshiro!
  • 8. 標準の関数と比べて● readLn >>= putStrLnとかできてカッコイイ!● 参照透過! ○ しかし、ScalaはIOを特別に見てくれるわけではないの で、unsafePerformIOを書かなければいけない。● 例外に対するメソッドがたくさんある。● unsafePerformIOをタイプするのが面倒。 
  • 9. STについて● 安全に可変状態を扱うためのもの。● 可変参照がつくれる。● 可変配列がつくれる。● STモナド内でしか変更できない。 ● runSTによってSTを実行し、値を取り出します。
  • 10. STモナドのための主な関数● def newVar [S, A] (a: A): ST[S, STRef[S, A]]● def newArr [S, A] (size: Int, z: A)(implicit arg0: Manifest[A]): ST[S, STArray[S, A]]● def returnST [S, A] (a: ⇒ A): ST[S, A]● def runST [A] (f: Forall[[S]ST[S, A]]): A
  • 11. STRefとSTArrayの主なメソッド● STRef ○ def write (a: ⇒ A): ST[S, STRef[S, A]] ○ def mod [B] (f: (A) ⇒ A): ST[S, STRef[S, A]] ○ def read : ST[S, A]● STArray ○ def write (i: Int, a: A): ST[S, STArray[S, A]] ○ def update [B] (f: (A, B) ⇒ A, i: Int, v: B): ST[S, Unit] ○ def read (i: Int): ST[S, A] ○ def freeze : ST[S, ImmutableArray[A]]
  • 12. STモナド(STRef)import scalaz._import effects._import Scalaz._val f = new Forall[({type X[S] = ST[S, String]})#X] { def apply[A] = for { v <- newVar[A, String]("Scala") // 参照を作る _ <- v.mod(_ |+| "Chan") // 値を取り出して文字を連結 s <- v.read // 値を取り出す  } yield s}runST(f) // 実行
  • 13. 結果scala> :load st.scalaLoading st.scala...import scalaz._import effects._import Scalaz._f: java.lang.Object with scalaz.Forall[[S]scalaz.effects.ST[S,java.lang.String]] =$$$$2c9d7a9074166de3bf8b66cf7c45a3ed$$$$anon$1@c8354eres17: java.lang.String = ScalaChan
  • 14. STモナド(STArray)import scalaz._import effects._import Scalaz._import ImmutableArray._val f = new Forall[({type X[S] = ST[S, ImmutableArray[String]]})#X] { def apply[A] = for { v <- newArr[A, String](5, "Scala") // 長さ5の配列を作り"Scala"で埋める    _ <- v.write(1, "Clojure") // 1番目を"Clojure"に書き換え    _ <- v.write(2, "JRuby") // 2番目を"JRuby"に書き換え    _ <- v.update(_ |+| (_: String), 3, "Chan") // 3番目を取り出し、連結 a <- v.freeze // ImmutableArrayで取り出す } yield a}runST(f).foreach(println) // 実行
  • 15. 結果scala> :load st.scalaLoading st.scala...import scalaz._import effects._import Scalaz._import ImmutableArray._f: java.lang.Object with scalaz.Forall[[S]scalaz.effects.ST[S,scalaz.ImmutableArray[java.lang.String]]] = $anon$1@e5e138ScalaClojureJRubyScalaChanScala
  • 16. 利点は?● HaskellではSTモナドを使えば安全に可変状態を扱 えるみたいですが、Scalaではvarがあるので必要がな い気がします。● Forall書くのがめんどいです。● newVar[RealWorld, A]みたいに書けばIO[A]に暗黙 的に変換してくれるので、unsafePerformIOで値を取り 出せます。● ScalaでSTモナドとはいったい・・・・・
  • 17. ファイル入力(rReadLn)import scalaz._import effects._import Scalaz._val file = new java.io.File("test.txt")val i = for { r <- bufferFile(file) // ファイルを開く  _ <- { // ファイルの終わりまで再帰的に出力する関数    def f(i: IO[Option[String]]): IO[Unit] = i >>= {      case Some(s) => putStrLn(s) >|> f(rReadLn(r))      case None => ().pure[IO] // 推論してくれないのが悲しい    }    f(rReadLn(r)) }  _ <- closeReader(r) // 閉じる} yield ()i.unsafePerformIO
  • 18. ファイル入力(Iteratee)import scalaz._import effects._import Scalaz._import IterV._val file = new java.io.File("test.txt")val i = for { xs <- for { // ファイルを読み込み、List[String]に変換    f <- getFileLines(file)(collect[String, List]) } yield f.run // IO[List[String]]が返る  _ <- xs.traverse_(putStrLn) // リストの内容を出力} yield ()i.unsafePerformIO
  • 19. 結果scala> :load iter.scalaLoading iter.scala...import scalaz._import effects._import Scalaz._import IterV._file: java.io.File = test.txti: scalaz.effects.IO[Unit] = scalaz.effects.IO$$anon$2@cfb016The source for Scalaz is now hosted on GitHub - http://github.com/scalaz/scalazScalaz is a library written in the Scala Programming Language. The intention ofScalaz is to include general functions that are not currentlyavailable in the core Scala API. The scalaz-core module depends only on the coreScala API and the core Java 2 Standard Edition API. Scalazis released under a BSD open source licence making it compatible with the licenceof the Scala project.Scalaz 6.0.1 was released in June 2011, targeting Scala 2.8.1 and 2.9.0.1.
  • 20. IterVについて● def collect [A, F[_]] (implicit mon: Monoid[F[A]], pr: Pure[F]): IterV[A, F[A]] ○ F[A]に変換します。 ○ 基本的にはこれを使うといいです。● def drop [E] (n: Int): IterV[E, Unit] ○ n個の要素を消費します● def head [E] : IterV[E, Option[E]] ○ 先頭要素を消費し、取得します● def peek [E] : IterV[E, Option[E]] ○ 先頭要素を消費せず、取得します● def length [E] : IterV[E, Int] ○ 要素全体の数を取得します。
  • 21. Iterateeのもっと詳しい説明● 続きはWebで☆● スミマセン。LTでやれる気がしないです。● 詳しい解説はblogに書こうと思います。
  • 22. Scalazでのファイル操作● 入力に関してはbufferFileなどを直接使わずに、Iterateeな 関数を使うと良いです。● getFileLinesは便利。closeは関数内でしている。● なぜか出力の関数はハブられてる。● closeWriterぐらいはあってもいいのではないか・・・・ ● まだいろいろと足りないイメージ。
  • 23. 参考資料など● Iterateeについて ○ Scalaz Tutorial: Enumeration-Based I/O with Iteratees ○ Lazy I/O must go! - Iteratee: 列挙ベースのI/O●本 ○ Real World Haskellーー実戦で学ぶ関数型言語プロ グラミング