【问题标题】:How to separate concerns functionally如何在功能上分离关注点
【发布时间】:2015-12-21 07:19:12
【问题描述】:

我正在用 Scala 编写一个程序,并试图尽可能保持功能上的纯正。我面临的问题不是 Scala 特有的;它更多地与尝试功能性编码有关。我必须编写的函数的逻辑类似于:

  1. 取一些 A 类型的值
  2. 使用该值生成日志信息
  3. 通过调用外部库中的函数记录此信息并评估日志记录操作的返回状态(即是成功的日志还是失败的日志操作)
  4. 无论日志成功还是失败,我都要返回输入值。

将输入值作为输出值返回的原因是该函数将与另一个需要 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)。

标签: functional-programming


【解决方案1】:

您所描述的听起来更像是调试而不是日志记录。例如,Haskell 的 Debug.Trace.trace 就是这样做的,它的文档指出:“这些对于调查错误或性能问题很有用。它们不应该在生产代码中使用。”

如果您正在记录日志,则日志记录函数应该只记录并且没有进一步的返回值。正如上面@Bartek 所提到的,它的类型是A -> IO (),即不返回任何信息() 并具有副作用(IO)。比如Haskell的hslogger library就提供了这样的功能。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-05-25
    • 1970-01-01
    • 2016-05-30
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多