2013-05-20 22 views
6

Monad yığınları ve monad transformatörlerini Scalaz7 ile anlamakta zorlanıyorum. Cevaba oldukça yakın olduğumu hissediyorum ama kafamı belirli bir adımda alamıyorum.Scalazda transformatörler ile monad yığınları arasında nasıl dönüşümü yaparım

Aşağıdaki kod, bir ffmpeg ikili için diske bakar, daha sonra çalıştırılacak bir çalıştırılabilir komut oluşturur, sonra bu komutu yürütür ve daha sonra çıktıyla önemsiz bir şey yapar.

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

kodu

Bu kod çalışır

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

çalıştırarak başladı, ancak callFfmpeg 'ın tipi imzası IO[Option[Stream[String]]] yerine IO[Stream[String]] olduğunu göreceksiniz. Ben kontrol etmek için bunu almak için bunu değiştirmek zorunda kaldı, ama gerçekten tüm callFfmpeg yok çağrı Stream döndüren bir işlem yürütmek olduğundan bu tür imza IO[Stream[String]] olmalıdır.

Soruma göre, callFfmpeg'u aradığımda IO[Option[String]] ile uğraşıyorum IO[Option[Stream[String]]]'a nasıl gidebilirim?

+0

Neden 'findFfmpeg' düz eski bir IO [Seçenek [Dize]] eylemi döndürmüyor ve sonra buna eşleme yapmıyor? –

cevap

1

Bu yüzden türünü liftM[OptionT] kullanarak dönüştürebiliyorum.

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

ve benim getStream işlevi artık olur:

Yani benim callFfmpeg işlevi olabilir

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

Bu Peşinde olduğum budur IO[Option[Stream[String]]] için IO[Stream[String]] dönüşümü sağlar.

İlgili konular