このScalaコードを理解するのを手伝ってください:Scalaz Io MonadとInflicits
質問
これはフォローアップです これ 質問。
これが私が理解しようとしているコードです(それはからです http://apocalisp.wordpress.com/2010/10/17/scalaz-tutorial-enumeration-io-with-italees/):
object io {
sealed trait IO[A] {
def unsafePerformIO: A
}
object IO {
def apply[A](a: => A): IO[A] = new IO[A] {
def unsafePerformIO = a
}
}
implicit val IOMonad = new Monad[IO] {
def pure[A](a: => A): IO[A] = IO(a)
def bind[A,B](a: IO[A], f: A => IO[B]): IO[B] = IO {
implicitly[Monad[Function0]].bind(() => a.unsafePerformIO,
(x:A) => () => f(x).unsafePerformIO)()
}
}
}
このコードはこのように使用されています(私は import io._
暗示されています)
def bufferFile(f: File) = IO { new BufferedReader(new FileReader(f)) }
def closeReader(r: Reader) = IO { r.close }
def bracket[A,B,C](init: IO[A], fin: A => IO[B], body: A => IO[C]): IO[C] = for { a <- init
c <- body(a)
_ <- fin(a) } yield c
def enumFile[A](f: File, i: IterV[String, A]): IO[IterV[String, A]] = bracket(bufferFile(f),
closeReader(_:BufferedReader),
enumReader(_:BufferedReader, i))
私は今理解しようとしています implicit val IOMonad
意味。これが私がそれを理解する方法です。これは Scalaz.monad, 、したがって、定義する必要があります pure
と bind
の抽象値 scalaz.Monad
特性。
pure
値を取り、「コンテナ」タイプに含まれる値に変換します。たとえば、それを取ることができます Int
aを返します List[Int]
. 。これは非常に簡単に思えます。
bind
「コンテナ」タイプと、コンテナが保持するタイプを別のタイプにマップする関数を採用します。返される値は同じコンテナタイプですが、現在は新しいタイプを保持しています。例は、を取ることです List[Int]
にマッピングします List[String]
マップする関数を使用します Int
s to String
s。は bind
ほとんど同じです map
?
の実装 bind
私が立ち往生しているところです。これがコードです:
def bind[A,B](a: IO[A], f: A => IO[B]): IO[B] = IO {
implicitly[Monad[Function0]].bind(() => a.unsafePerformIO,
(x:A) => () => f(x).unsafePerformIO)()
}
この定義には必要です IO[A]
マップします IO[B]
を取る関数を使用します A
と返します IO[B]
. 。私はこれを行うために、それは使用する必要があると思います flatMap
結果を「フラット化」する(正しい?)。
= IO { ... }
と同じです
= new IO[A] {
def unsafePerformIO = implicitly[Monad[Function0]].bind(() => a.unsafePerformIO,
(x:A) => () => f(x).unsafePerformIO)()
}
}
おもう?
implicitly
メソッドは、実装する暗黙の値(値、右?)を探します Monad[Function0]
. 。この暗黙の定義はどこから来たのですか?これはからだと思います implicit val IOMonad = new Monad[IO] {...}
定義ですが、私たちは今その定義の中にあり、物事は少し円形になり、私の脳は無限のループで立ち往生し始めます:)
また、最初の議論 bind
(() => a.unsafePerformIO
)パラメーターを取得せず、A.Unsafeperformioを返す関数のようです。これをどのように読むべきですか? bind
コンテナタイプを最初の引数として取るので、多分 () => a.unsafePerformIO
コンテナタイプに解決しますか?
正しい解決策はありません