我有以下代码使用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