2013-05-20 8 views
6

Sto lottando con la comprensione di monad stack e trasformatori monad con Scalaz7. Sento che sono abbastanza vicino alla risposta, ma non riesco a capire la situazione.Come convertire tra stack monad con trasformatori in scalaz 7

Il seguente codice cerca sul disco un binario ffmpeg, quindi crea un comando eseguibile da eseguire, quindi esegue quel comando e quindi fa qualcosa di banale con l'output.

object Encoder { 

    def findFfmpeg: OptionT[IO, String] = { 
    OptionT[IO, String](IO { 
     List("/usr/local/bin/ffmpeg", "/usr/bin/ffmpeg").find { 
     new File(_).exists 
     } 
    } 
    ) 
    } 

    def getCommand(ffmpegBin: String, 
       videoFile: String) = s"$ffmpegBin $videoFile '-vcodec libx264 -s 1024x576' /tmp/out.mp4" 

    def callFfmpeg(command: String): IO[Option[Stream[String]]] = IO { 
    Some(Process(command).lines_!) 
    } 

    def getStream(fileName: String): OptionT[IO, Stream[String]] = { 
    val optionalCommand: OptionT[IO, String] = findFfmpeg map { 
     getCommand(_, fileName) 
    } 
    optionalCommand >>= { 
     command => OptionT[IO, Stream[String]](callFfmpeg(command)) 
    } 
    } 

    def encode(fileName: String): IO[Unit] = { 
    getStream(fileName) map { 
     a: Stream[String] => 
     a map { 
      _.length 
     } foreach (println) 

    } getOrElse (Unit.box {println("nothing")}) 
    } 
} 

il codice viene dato il via eseguendo

Encoder.encode("/path/to/video.mp4").unsafePerformIO 

Questo codice funziona, ma si noterà che callFfmpeg 's tipo di firma è IO[Option[Stream[String]]] invece di IO[Stream[String]]. Ho dovuto cambiarlo per farlo controllare il tipo, ma dal momento che tutto il callFfmpeg fa è chiamare eseguire un processo che restituisce un Stream la sua firma dovrebbe essere IO[Stream[String]].

La mia domanda è, dato che al momento chiamo callFfmpeg ho a che fare con IO[Option[String]] come posso arrivare a IO[Option[Stream[String]]]?

+0

Perché non trovare "findFfmpeg" restituisce una semplice vecchia azione "IO [Opzione [String]]' e quindi mappare in quella? –

risposta

1

Quindi sono riuscito a trasformare il tipo utilizzando liftM[OptionT].

Quindi la mia funzione callFfmpeg può diventare:

def callFfmpeg(command: String): IO[Stream[String]] = IO { 
    Process(command).lines_! 
} 

e la mia funzione getStream diviene ora:

def getStream(fileName: String): OptionT[IO, Stream[String]] = { 
    val optionalCommand: OptionT[IO, String] = findFfmpeg map { 
     getCommand(_, fileName) 
    } 
    optionalCommand >>= { 
     command => callFfmpeg(command).liftM[OptionT] 
    } 
} 

Questo permette la conversione da IO[Stream[String]] a IO[Option[Stream[String]]] che è quello che sto cercando.

Problemi correlati