gpt4 book ai didi

scala - 如何避免在scala中使用Monad Transformers的阶梯?

转载 作者:行者123 更新时间:2023-12-04 02:02:23 41 4
gpt4 key购买 nike

我有以下使用 Reader 的代码monad 用于配置,还必须处理 IO[Option[String]]我最终得到了在我的 encode 中阶梯式执行的代码功能。

如何为 Reader 制定单子(monad)变压器和 OptionT避免丑陋的嵌套 for我的 encode 中的理解功能?

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

谢谢!

最佳答案

如果您查看 definition of Reader in the Scalaz source ,你会看到:

    type Reader[-E, +A] = ReaderT[Id, E, A]

这告诉我们 Reader您正在使用的 monad 只是 monad 转换器的一个特化,其中被包裹的 monad 是微不足道的 Id单子(monad)。您可以使用 ReaderT直接,但包装你的 OptionT[IO, _] monad 而不是将所有内容都包装在 Reader 中.例如,以下应该做你想要的:
type OptionIO[+A] = OptionT[IO, A]

def findFfmpeg: ReaderT[OptionIO, Config, String] =
Kleisli[OptionIO, Config, String](c => findFile(c.ffmpegLocations))

def findFfmpegWrapper: ReaderT[OptionIO, Config, String] =
Kleisli[OptionIO, Config, String](c => findFile(c.ffmpegWrapperLocations))

def encode(fileName: String): ReaderT[OptionIO, Config, Unit] = (for {
w <- findFfmpegWrapper
b <- findFfmpeg
stream <- Kleisli[OptionIO, Config, Stream[String]](
_ => callFfmpeg(getCommand(w, b, fileName)).liftM[OptionT]
)
} yield stream).map(_ foreach println)

原则上,您应该能够更换 stream <- 之后的部件。具有以下内容:
callFfmpeg(getCommand(w, b, fileName)).liftM[OptionT].liftReaderT[Config]

但由于某种原因 Unapply机械 liftReaderT在这种情况下,依赖似乎不起作用。写 Kleisli幸运的是,明确分手并不是那么可怕。

作为脚注:不错的 liftReaderT如果您定义 UnapplyCo,我提到的语法将可用。像这样的例子:
implicit def unapplyMFA1[TC[_[_]], F[+_], M0[F[+_], +_], A0](
implicit TC0: TC[({ type L[x] = M0[F, x] })#L]
): UnapplyCo[TC, M0[F, A0]] {
type M[+X] = M0[F, X]
type A = A0
} = new UnapplyCo[TC, M0[F, A0]] {
type M[+X] = M0[F, X]
type A = A0
def TC = TC0
def leibniz = Leibniz.refl
}

我不确定Scalaz 7目前不提供此实例是否有原因,但它可能值得研究。

关于scala - 如何避免在scala中使用Monad Transformers的阶梯?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17062119/

41 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com