我有以下代碼使用Reader
monad進行配置,並且還必須處理IO[Option[String]]
,並且我已經使用我的encode
函數中的階梯代碼結束了代碼。如何避免scala中使用Monad變形金剛階梯式步進?
我怎樣才能制定一個單子轉換爲Reader
和OptionT
避免我encode
功能醜陋的嵌套for
內涵?
def encode(fileName: String): Reader[Config, IO[Unit]] = for {
ffmpegWrapper <- findFfmpegWrapper
ffmpegBin <- findFfmpeg
} yield (for {
w <- ffmpegWrapper
b <- ffmpegBin
stream <- callFfmpeg(getCommand(w, b, fileName)).liftM[OptionT]
} yield stream) map (_ foreach (println)) getOrElse Unit.box {}
def getCommand(ffmpegWrapper: String, ffmpegBin: String,
videoFile: String) = s"$ffmpegWrapper $ffmpegBin $videoFile '-vcodec libx264 -s 1024x576' /tmp/out.mp4"
def callFfmpeg(command: String): IO[Stream[String]] = IO {
Process(command).lines_!
}
def findFile(path:List[String]): OptionT[IO,String] = OptionT[IO,String](IO{path.find(new File(_).exists)})
def findFfmpeg:Reader[Config, OptionT[IO,String]] = Reader {c=>findFile(c.ffmpegLocations)}
def findFfmpegWrapper:Reader[Config, OptionT[IO,String]] = Reader {c=>findFile(c.ffmpegWrapperLocations)}
謝謝!
當你出現時,我正在寫一個幾乎相同的答案。我修改了你的答案的頂部,這些東西是在我的,但沒有在你的顯示Reader = ReaderT類型別名,請隨時刪除它,如果你認爲它不會添加到您的答案:) – stew
@stew:謝謝!我剛剛添加了一個鏈接到您提到的來源。 –
特拉維斯和@stew這非常有幫助!現在就試試吧。 – cwmyers