【发布时间】:2015-12-21 07:19:12
【问题描述】:
我正在用 Scala 编写一个程序,并试图尽可能保持功能上的纯正。我面临的问题不是 Scala 特有的;它更多地与尝试功能性编码有关。我必须编写的函数的逻辑类似于:
- 取一些 A 类型的值
- 使用该值生成日志信息
- 通过调用外部库中的函数记录此信息并评估日志记录操作的返回状态(即是成功的日志还是失败的日志操作)
- 无论日志成功还是失败,我都要返回输入值。
将输入值作为输出值返回的原因是该函数将与另一个需要 A 类型值的函数组成。
鉴于上述情况,我要编写的函数实际上是 A => A 类型的,即它接受 A 类型的值并返回 A 类型的值,但在两者之间它会进行一些日志记录。我返回的值与我输入的相同,这一事实使这个函数归结为一个恒等函数!
这对我来说看起来像是代码异味,我想知道我应该怎么做才能使这个函数更干净。我怎样才能把这里的问题分开?此外,日志函数消失并记录信息这一事实意味着我真的应该将该调用包装在 IO monad 中并在其上调用一些 unsafePerformIO 函数。欢迎任何想法。
【问题讨论】:
-
如果它的唯一目的是记录,它应该是
A -> IO ()而不是A -> A。 -
虽然日志功能不一定与 IO 有任何关系,但您也许可以使用 Writer Monad,留下一个
A => Writer A类型的函数,然后您可以执行 IO 上的操作 -
我接受了@BartekBanachewicz 的建议,并将函数签名更改为
A -> IO[Unit]。然后,我在 for 表达式中用这个 IO 操作单子组合其他函数(等效于 Haskell 中的do)。