2013-05-20 5 views
6

में ट्रांसफॉर्मर के साथ मोनैड स्टैक्स के बीच मैं कैसे परिवर्तित करूं मैं Scalaz7 के साथ मोनैड स्टैक्स और मोनैड ट्रांसफार्मर को समझने के साथ संघर्ष कर रहा हूं। मुझे लगता है कि मैं जवाब के बहुत करीब हूं लेकिन सिर्फ एक विशेष कदम के आसपास मेरा सिर नहीं मिल सकता है।स्केलज़ 7

निम्नलिखित कोड ffmpeg बाइनरी के लिए डिस्क पर दिखता है, फिर चलाने के लिए एक निष्पादन योग्य आदेश बनाता है, फिर उस आदेश को निष्पादित करता है और फिर आउटपुट के साथ कुछ छोटा करता है।

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

कोड

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

चल रहा यह कोड काम करता है द्वारा शुरू हुआ है, लेकिन आप देखेंगे कि callFfmpeg के प्रकार हस्ताक्षर IO[Option[Stream[String]]] बजाय IO[Stream[String]] है। मुझे इसे टाइप करने के लिए इसे बदलना पड़ा, लेकिन वास्तव में सभी callFfmpeg कॉल को एक प्रक्रिया निष्पादित करता है जो Stream देता है, इसका प्रकार हस्ताक्षर IO[Stream[String]] होना चाहिए।

मेरा सवाल यह है कि, जब मैं callFfmpeg पर कॉल करता हूं तो मैं IO[Option[String]] से निपट रहा हूं मैं IO[Option[Stream[String]]] पर कैसे जा सकता हूं?

+0

क्यों नहीं ढूंढें 'findFfmpeg' एक सादा पुराना 'IO [विकल्प [स्ट्रिंग]]' कार्रवाई वापस करें और फिर उसमें मानचित्र करें? –

उत्तर

1

इसलिए मैंने liftM[OptionT] का उपयोग कर प्रकार को बदलने में कामयाब रहा है।

तो मेरी callFfmpeg समारोह बन सकता है:

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

और मेरे getStream समारोह अब हो जाता है:

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

यह जो है कि मैं क्या कर रहा हूँ के बाद IO[Option[Stream[String]]] को IO[Stream[String]] से रूपांतरण की अनुमति देता है।