gpt4 book ai didi

scala - 处理 FP、IO Monad 中不纯的副作用

转载 作者:行者123 更新时间:2023-12-05 00:10:51 24 4
gpt4 key购买 nike

试图了解如何最好地处理 FP 中的副作用。

我实现了这个基本的 IO 实现:

  trait IO[A] {
def run: A
}
object IO {
def unit[A](a: => A): IO[A] = new IO[A] { def run = a }
def loadFile(fileResourcePath: String) = IO.unit[List[String]]{
Source.fromResource(fileResourcePath).getLines.toList }
def printMessage(message: String) = IO.unit[Unit]{ println(message) }
def readLine(message:String) = IO.unit[String]{ StdIn.readLine() }
}

我有以下用例:
- load lines from log file
- parse each line to BusinessType object
- process each BusinessType object
- print process result

情况1:
所以 Scala 代码可能看起来像这样
val load: String => List[String]
val parse: List[String] => List[BusinessType]
val process: List[BusinessType] => String
val output: String => Unit

案例2:
我决定使用上面的IO:
val load: String => IO[List[String]]
val parse: IO[List[String]] => List[BusinessType]
val process: List[BusinessType] => IO[Unit]
val output: IO[Unit] => Unit

在第 1 种情况下,负载是不纯的,因为它是从文件中读取的,因此输出也是不纯的,因为它将结果写入控制台。

为了更实用,我使用案例 2。

问题:
- Aren't case 1 and 2 really the same thing?
- In case 2 aren't we just delaying the inevitable?
as the parse function will need to call the io.run
method and cause a side-effect?
- when they say "leave side-effects until the end of the world"
how does this apply to the example above? where is the
end of the world here?

最佳答案

您的 IO monad 似乎缺少所有 monad 的东西,即您可以使用的部分 flatMap在它之上以较小的 IO 构建更大的 IO。这样,一切都保持“纯净”,直到调用 run在最后。

In case 2 aren't we just delaying the inevitable? as the parse function will need call the io.run method and cause a side effect?



parse函数不应调用 io.run .它应该返回另一个 IO,然后您可以将其与其输入 IO 结合。

when they say "leave side-effects until the end of the world" how does this apply to the example above? where is the end of the world here?



世界末日将是您的程序所做的最后一件事。你只 run一次。程序的其余部分“纯粹”为此构建了一个巨大的 IO。

就像是
def load(): IO[Seq[String]]    
def parse(data: Seq[String]): IO[Parsed] // returns IO, because has side-effects
def pureComputation(data: Parsed): Result // no side-effects, no need to use I/O
def output(data: Result): IO[Unit]

// combining effects is "pure", so the whole thing
// can be a `val` (or a `def` if it takes some input params)
val program: IO[Unit] = for {
data <- load() // use <- to "map" over IO
parsed <- parse()
result = pureComputation(parsed) // = instead of <-, no I/O here
_ <- output(result)
} yield ()

// only `run` at the end produces any effects
def main() {
program.run()
}

关于scala - 处理 FP、IO Monad 中不纯的副作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56169426/

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