Jef*_*ner 21 logging functional-programming purely-functional
我更倾向于尽可能地接近功能范例,当我的大脑迎接挑战时,尽可能地挤压到纯粹的功能.我尽可能使用F#.通常,我会遇到VB.NET或C#(或VBA,当我真的不走运时).所以我的语言让我偏离了功能方法.
从历史上看,我已经忽略了日志记录并与用户通信,直到我得到结果 - 让用户等待.现在我正在尝试实现状态栏的记录和/或更新.这很容易,因为我的语言允许我随时写入标准输出.但是从一个纯粹的功能角度来看,如何将一个人的功能泄露到外部世界?在计算过程中记录或与用户通信是否与纯功能方法相反?
我敢肯定在Haskell中会使用Monad.使用其他语言时呢?
谢谢.
让我们来看看Haskell的monadic解决方案.日志记录背后的想法是我们的计算有一个额外的方法,可以在某个地方"输出".有很多方法可以表示这样的计算,但最常见的一种方法是制作一个monad:
class (Monad m) => MonadWriter w m | m -> w where
tell :: w -> m ()
Run Code Online (Sandbox Code Playgroud)
Type w表示消息,函数tell是将消息"发送"到monadic(效果完整)计算中.
笔记:
MonadWriter实际上更丰富,它包含允许检查和修改的功能w,但是让我们暂时搁置一边.| m -> w部分对于解释并不重要,它只是意味着w对于给定的是固定的m.最常用的实现是Writer,它基本上只是一对.其中一个元素是计算结果,另一个元素是一系列书面消息.(实际上它不是一个真正的序列,它更通用 - 一个monoid,它定义了将多个消息组合成一个的操作.)您可以通过查看Writer模块来检查Haskell的解决方案.然而,更WriterT常见的是,使用monad变换器,所以如果你不是monad粉丝,那么它很难阅读.同样的事情也可以在其他函数语言中完成,例如在Scala中查看此示例.
但是还有其他可能的,更多的面向副作用(仍然是功能)的上述类型的实现.我们可以定义tell将消息发送到某些外部接收器,例如stdout,文件等.例如:
{-# LANGUAGE FunctionalDependencies, TypeSynonymInstances, FlexibleInstances #-}
instance MonadWriter String IO where
tell = putStrLn
Run Code Online (Sandbox Code Playgroud)
这里我们说IO可以用作将Strings写入stdout 的日志记录工具.(这只是一个简化的例子,一个完整的实现可能会有一个monad转换器,可以tell为任何IO基于monad的monad 添加功能.)
我是函数编程的新手,但这是Scala中的尝试:
object FunctionalLogging {
type Result = Int
class ResultWithLogging(val log: List[String], val result: Result) {}
def functionWithLogging(log: List[String], arg: String): ResultWithLogging = {
def function(arg: String): Result = arg.length
new ResultWithLogging(log :+ ("Calling function(" + arg +")"), function(arg))
}
val result = functionWithLogging(List(), "Hello world!")
// -- Pure functional code ends here --
println("Result = " + result.result)
println("Log = " + result.log)
}
Run Code Online (Sandbox Code Playgroud)
它的功能是没有副作用,但是很显然,日志是函数参数和返回值的一部分,因此它不是非常优雅或实用。
在我看来,按照定义,日志记录是理想的副作用,因此,如果按照我的定义,问题是如何将非功能性代码与功能性代码隔离。在实践中,我可能会从一个Scala对象开始(可能太像一个单例对象了-一个特性可能更适合Scala),或者是一个Actor来积累日志消息并执行需要对它们进行的所有操作。
这是一个更为实用的视图:登录Scala
编辑
这个问题是关于Haskell Monads和IO的:除了Monads之外,还可以用纯函数式语言处理状态的其他哪些方式?