Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/logging/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Logging 如何登录Haskell?_Logging_Haskell_Monads - Fatal编程技术网

Logging 如何登录Haskell?

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

我正在尝试使用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.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) }