2013-05-20 9 views
6

Mam problemy ze zrozumieniem stosów Monady i transformatorów Monady z Scalaz7. Czuję, że jestem całkiem blisko odpowiedzi, ale nie mogę pojąć się konkretnym krokiem.Jak przekonwertować stosy monad z transformatorami w skalażu 7

Następujący kod wygląda na dysku dla pliku binarnego ffmpeg, a następnie tworzy polecenie do wykonania, a następnie wykonuje to polecenie, a następnie robi coś trywialnego z danymi wyjściowymi.

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

Kod jest skopany przez uruchomienie

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

Ten kod działa, ale można zauważyć, że callFfmpeg „s typ podpis jest IO[Option[Stream[String]]] zamiast IO[Stream[String]]. Musiałem to zmienić, aby uzyskać sprawdzenie typu, ale tak naprawdę, ponieważ wszystkie callFfmpeg to wywołanie procesu, który zwraca Stream jego podpis typu powinien być IO[Stream[String]].

Moje pytanie brzmi, biorąc pod uwagę, że w czasie kiedy dzwonię pod numer callFfmpeg mam do czynienia z IO[Option[String]] jak dostać się do IO[Option[Stream[String]]]?

+0

Dlaczego 'findFfmpeg' nie powróci do zwykłej akcji' IO [Option [String]] ', a następnie odwzoruje w niej? –

Odpowiedz

1

Więc udało mi się przekształcić typ za pomocą liftM[OptionT].

Więc moja callFfmpeg funkcja może stać:

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

i mój getStream funkcja staje się teraz:

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

To pozwala na konwersję z IO[Stream[String]] do IO[Option[Stream[String]]] który jest co jestem po.

Powiązane problemy