Logging 如何登录Haskell?
我正在尝试使用HSlogger获取有关我的程序的一些信息。因此,我在函数中添加以下行Logging 如何登录Haskell?,logging,haskell,monads,Logging,Haskell,Monads,我正在尝试使用HSlogger获取有关我的程序的一些信息。因此,我在函数中添加以下行 import Data.Word import qualified Data.ByteString as B import qualified Data.ByteString.Lazy as L import Data.Bits import Data.Int import Data.ByteString.Parser import System.Log.Logger import System.Log.Ha
import Data.Word
import qualified Data.ByteString as B
import qualified Data.ByteString.Lazy as L
import Data.Bits
import Data.Int
import Data.ByteString.Parser
import System.Log.Logger
import System.Log.Handler.Syslog
importFile :: FilePath -> IO (Either String (PESFile ))
importFile n = do
warningM "MyApp.Component2" "Something Bad is about to happen."
...
这很好,因为函数在IO内部。
但是,当我向以下函数添加类似的行时:
...
parsePES :: Parser PESFile
parsePES = do
header <- string "#PES"
warningM "parsing header"
...
return (PESFile ...)
。。。
parsePES::Parser-pes文件
parsePES=do
头IO()'
在“warningM”调用的返回类型中
在“do”表达式的stmt中:warningM“parsing header”
在表达式中:
首先,一个快速的免责声明:“logging”在一般的Haskell代码中通常没有意义,因为它假定某种顺序执行可能有意义,也可能没有意义。请确保区分记录程序的执行方式和记录计算的值。在严格命令式语言中,它们基本相同,但在Haskell中则不同
这就是说,听起来您希望在已连续且有状态计算的上下文中,基于正在计算的值进行日志记录,这与大多数其他语言中的日志记录工作原理基本相同。但是,您确实需要monad来支持某种方法。看起来您正在使用的解析器是,它似乎与Ictive limited,不允许IO
,并且未定义为monad转换器
我的忠告是考虑使用一个不同的解析库。它往往是默认的选择,我认为对于特定的目的很流行(可能包括你正在做的事情)。。两者都可以让您更轻松地添加日志记录:Parsec是一个单变量转换器,因此您可以将其置于IO
之上,然后根据需要使用liftIO
,而attoparsec是围绕增量处理设计的,因此您可以分块输入并记录处理的各个方面(虽然在实际的解析器中登录可能会更麻烦)。还有其他选择,但我对细节了解不够,无法提出建议。大多数基于parser combinator的库往往具有相当类似的设计,因此我希望移植代码会很简单
最后一个选择,如果你真的想坚持你所拥有的,那就是看看你现在正在使用的解析库的实现,并推出你自己的面向IO
的版本。但这可能并不理想
另外,作为补充,如果您真正想要的不是真正的日志记录,而是作为开发的一部分跟踪程序的执行,那么您可能会发现内置在GHCi中的调试器更有用,或者是老式的printf调试
< > > >编辑< /强>:好的,听起来好像有合理的理由来考虑你自己的变化。你大概想要的是一个<代码> ParserT <代码>一元转换器。这里是“代码>语法分析器< /代码>:的当前定义。
newtype Parser a = Parser { unParser :: S -> Either String (a, S) }
类型S
是解析器状态。请注意,这大致是StateT S(任一字符串)a
的硬编码版本:
newtype StateT s m a = StateT { runStateT :: s -> m (a,s) }
…其中,任一字符串
被视为错误monad。error t
monad转换器执行相同的操作:
newtype ErrorT e m a = ErrorT { runErrorT :: m (Either e a) }
因此,当当前类型相当于StateT S(error字符串标识)
时,您需要的是StateT S(error字符串IO)
看起来模块中的大多数函数都没有弄乱解析器
monad的内部结构,因此您应该能够简单地替换类型定义,提供适当的类型类实例,编写自己的运行解析器
函数,然后就可以了。免责声明:我是
尽管McCann的回答非常详细,但没有说明Haskell在提出问题时缺乏通用的日志框架。HSLogger现在是一个标准,但它提供了非常基本的日志功能,但速度慢且不可扩展。需要明确的是,HSLogger存在以下一些缺陷:
它很慢。我所说的慢,是指每次你记录一条消息时
解析(以一种非常简单的方式)描述日志来源的字符串,并在后台使用一些存在的数据类型,这在运行时会带来一些性能开销
它不允许登录IO以外的其他monad,因此您必须使用WriterT
或其他解决方案来避免代码混乱
它是不可扩展的-您不能创建自己的优先级、定义自定义行为(如线程间日志记录)或编译时日志过滤
它不提供一些信息,比如日志所在的行号或文件名。当然,很难扩展它来支持这些信息
尽管如此,我还是想介绍。它允许高效和可扩展的日志记录,包括:
登录顺序纯代码(执行和使用WriterT
monad)
高级消息筛选(包括编译时筛选)
线程间日志记录能力
提供TemplateHaskell
接口,允许记录其他详细信息,如文件号或模块名
非常容易扩展-所有功能都是作为简单的BaseLogger
的扩展创建的,它不能做任何合理的事情。需要明确的是,过滤功能是作为记录器转换器在不到20行中创建的,您可以定义自己的转换器。中介绍了如何执行
默认情况下,在所有平台上提供彩色输出
但是这个库非常新,所以它可能缺少一些需要的功能。好消息是,您可以自己轻松创建这个功能,或者通过在GitHub上报告问题来帮助我们改进它
该记录器由我所在的公司()内部开发,并在我们正在创建的编译器中使用。无耻插件:我是co-log
日志库的作者。您可以
newtype ErrorT e m a = ErrorT { runErrorT :: m (Either e a) }