haskell - 使用自定义数据类型过滤列表

标签 haskell

我刚刚开始使用 Haskell。我正在使用它进行日志解析,并且我正在尝试过滤日志。但出现与 TypeMismatch 相关的错误。

这就是我所做的。

我的数据类型

data LogExStack = LogExStack {
    methodName :: String,
    className :: String,
    extraInfo :: String
} | List [LogExStack] deriving Show
data LogException = LogException {
    exFirstLine :: LogExFirstLine,
    exMessage :: LogExMessage,
    exStackTrace :: LogExStack
} deriving Show

我想要对 LogExStack 类型数据进行过滤。 我创建该列表的函数看起来像这样

exceptionStackTraceParser :: Parser LogExStack
exceptionStackTraceParser =
    M.liftM List $ sepBy exceptionParser newLinesTabEx


exceptionParser :: Parser LogExStack
exceptionParser =
    do
        string "at"
        method <- many (noneOf "(")
        string "("
        className <- many (noneOf ")")
        string ")"
        extraInfo <- many (noneOf "\n")
        string "\n"
        return $ LogExStack method className extraInfo

到目前为止,一切都很好,但是当我尝试使用列表进行过滤时,它不起作用。我想对 LogExStack 列表中的 methodName 进行过滤。

这是我的功能

filterStackTrace :: [LogExStack] -> [LogExStack]
filterStackTrace  = filter (\r -> methodName r == "com.xyz.abc")

我也尝试过不使用[],但也失败了。谁能帮我这个。 我从这里获取了实现的引用

https://en.wikibooks.org/wiki/Write_Yourself_a_Scheme_in_48_Hours/Parsing

Filter a haskell data type

有人可以帮我解决这个问题吗? 谢谢

编辑

这是我在阅读 Arnon 帖子后所做的更改

exceptionStackTraceParser :: Parser [LogExStack]
exceptionStackTraceParser =
    sepBy exceptionParser newLinesTabEx

这是我调用过滤器的方式

parseExpr :: Parser LogException
parseExpr = 
    do
        fstLine <- exceptionFirstLineParser
        msgLine <- exceptionMessageParser
        stackTrace <- exceptionStackTraceParser
        list <- filterStackTrace stackTrace
        return $ LogException fstLine msgLine list

这是我的异常(exception)

H:\>ghc --make -O logparser.hs
[1 of 1] Compiling Main             ( logparser.hs, logparser.o )

logparser.hs:69:25:
    Couldn't match type `[]'
                  with `Text.Parsec.Prim.ParsecT
                          String () Data.Functor.Identity.Identity'
    Expected type: Text.Parsec.Prim.ParsecT
                     String () Data.Functor.Identity.Identity LogExStack
      Actual type: [LogExStack]
    In a stmt of a 'do' block: list <- filterStackTrace stackTrace
    In the expression:
      do { fstLine <- exceptionFirstLineParser;
           msgLine <- exceptionMessageParser;
           stackTrace <- exceptionStackTraceParser;
           list <- filterStackTrace stackTrace;
           .... }

编辑2 明白了,我从错误的地方调用列表过滤器,不知怎的,我无法从 parseExpr 函数调用,因为我不知道它认为从那里调用的函数必须是 Parsec 类型。

不知道为什么?谁能帮我理解这一点吗?

最佳答案

我只能假设您错误地调用了过滤器:

您定义了自己的数据类型List [LogExStack],但您的filterStackTrace仅接受[LogExStack]。因此,在调用 filterStackTrace 之前,您需要从 List 构造函数中“提取”实际列表,也许可以通过在 filterStackTrace 中进行模式匹配来实现子句:

filterStackTrace :: LogExStack -> LogExStack
filterStackTrace  (List l) = List $ filter (\r -> methodName r == "com.xyz.abc") l

编辑: 实际上,再想一想,在这里定义自己的列表类型有点奇怪。 为什么不将数据类型设置为

data LogExStack = LogExStack {
    methodName :: String,
    className :: String,
    extraInfo :: String
} deriving Show

然后更改解析器以返回 LogExStack 的正确列表版本

exceptionStackTraceParser :: Parser [LogExStack]
exceptionStackTraceParser =
    sepBy exceptionParser newLinesTabEx

然后按照您最初编写的方式调用filterStackTrace

编辑2,作为回应: 您错过了对 parse 的调用。 这个简单的程序对我有用:

module Main where
import Text.Parsec
import Text.Parsec.String

data LogExStack = LogExStack {
    methodName :: String,
    className :: String,
    extraInfo :: String
} deriving Show

exceptionParser :: Parser LogExStack
exceptionParser =
    do
        _ <- string "at"
        method <- many (noneOf "(")
        _ <- string "("
        className' <- many (noneOf ")")
        _ <- string ")"
        extraInfo' <- many (noneOf "\n")
        _ <- string "\n"
        return $ LogExStack method className' extraInfo'

exceptionStackTraceParser :: Parser [LogExStack]
exceptionStackTraceParser =
    exceptionParser `sepBy` newLinesTabEx
  where
    newLinesTabEx = oneOf "\t\r\n"

main :: IO ()
main = do
     case (parse exceptionParser "example" "bla bla bla bla") of
      Left err -> print $ "Error: " ++ show err
      Right xs -> print xs

关于haskell - 使用自定义数据类型过滤列表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31127605/

相关文章:

Haskell:输入 `import' 时出现解析错误

haskell - 右左如何读取值

android - 如何让 JHC 与 android ndk 合作?

linux - Haskell make recipe 使用 GHC 的悖论定理证明器失败

haskell - 如何在 Haskell 中对列表进行分区?

haskell - cabal 报告 "/usr/bin/ld: cannot find -lHSrandom-1.0.1.1-ghc7.8.3"

haskell - 在 Haskell 中从无限循环(C 程序)中获取每个换行符的数据

haskell - 如何使免费的 monad 解释器递归?

haskell - "higher order Traversable"类应该是什么样的?

haskell - 带有中缀函数的偏应用