使用自定义数据类型

时间:2015-06-30 00:19:38

标签: 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

这是我的例外

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类型。

我不知道为什么?任何人都可以帮我理解吗?

1 个答案:

答案 0 :(得分:2)

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

您定义了自己的数据类型List [LogExStack],但filterStackTrace仅接受[LogExStack]。因此,您需要提取&#39;调用List之前filterStackTrace构造函数中的实际列表,可能是通过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