我刚刚开始使用 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
有人可以帮我解决这个问题吗? 谢谢
编辑
这是我在阅读 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/