【问题标题】:Filter in List with custom data types使用自定义数据类型过滤列表
【发布时间】:2015-06-30 00:19:37
【问题描述】:

我刚刚开始使用 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

这是我的例外

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;
           .... }

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

我不知道为什么?谁能帮我理解一下?

【问题讨论】:

  • 您有确切的错误信息吗?它看起来不像是类型不匹配。
  • 一个不相关的错误是 LogExStack 可能没有 methodName。你会想要处理它。
  • @PyRulez 我已经添加了错误详情。

标签: haskell


【解决方案1】:

我只能假设你调用过滤器是错误的:

您定义了自己的数据类型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

【讨论】:

  • 我已经按照您所说的进行了更改,但仍然显示类型错误,我已经编辑了我的问题
  • @NixitPatel 我更新了我的答案,看看那个例子
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-04-09
  • 2015-08-09
  • 1970-01-01
相关资源
最近更新 更多