2011-09-13 5 views
4

Voici le code que je suis en train de comprendre (c'est de http://apocalisp.wordpress.com/2010/10/17/scalaz-tutorial-enumeration-based-io-with-iteratees/):Aidez-moi à comprendre ce code Scala: scalaz monade IO

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)() 
    } 
    } 
} 

Ce code est utilisé comme ceci (je suppose une import io._ est implicite)

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)) 

Commençons par la définition bufferFile. Ai-je raison de penser que la méthode apply de io.IO est appelée? Cette méthode apply prend une fonction sans paramètre qui renvoie une valeur (correct?). Je suppose que c'est là où je suis coincé. Quelqu'un peut-il expliquer comment fonctionne la définition de bufferFile?

Répondre

5

Oui, vous avez raison, eh bien presque; io.IO.apply est appelé avec un paramètre appelé "par nom" qui est essentiellement une fonction qui ne prend rien (Unit) et renvoie A. La chose cool est que lorsque vous passez une instance de A directement comme new BufferedReader(new FileReader(f)), il sera converti en quelque chose comme () => new BufferedReader(new FileReader(f)).

À la suite de apply vous obtenez une instance d'un IO[BufferedReader] qui définit une méthode def unsafePerformIO qui renvoie simplement l'instance du BufferedReader capturé.

2

de answer Complétant agilesteel, le code

def bufferFile(f: File) = IO { new BufferedReader(new FileReader(f)) } 

est équivalent à

def bufferFile(f: File) = new IO[A] { 
    def unsafePerformIO = { new BufferedReader(new FileReader(f)) } 
}