Haskell ***例外:Prelude.read:没有解析

时间:2016-09-10 12:31:49

标签: parsing haskell parse-error

您好我正在尝试完成CIS194 Spring 13,当我在其中一个函数上收到错误消息*** Exception: Prelude.read: no parse时。函数所在的文件名为LogAnalysis.hs,函数为parseMessage,但该文件也从Log.hs导入。为什么我会发现此错误消息以及如何解决?

这是我的代码: https://github.com/Adam-Morris/CIS194/tree/master/Homework-2

2 个答案:

答案 0 :(得分:2)

read是类型为read :: Read a => String -> a的函数。这意味着readString作为输入,并返回某种类型a的值,前提是a实现了Read类型类。 read必须知道要返回的具体类型,并且可以通过以下两种方式之一知道:要么明确地给出类型(例如read "123" :: Intread "True" :: Bool),要么推断它它来自上下文。在您的情况下,read推断它必须返回Int,因为LogMessage期望Int作为其第二个参数。因此,在这种情况下,表达式read [y]表示:取Char y,将其转换为单元素字符串,然后尝试将其转换为Int,解析它。现在,如果y恰好包含一个不是十进制数字的字符,它将失败(通过抛出异常),因为它不知道如何将其转换为整数。

现在你怎么处理这个问题?在调用之前,您必须检查read的输入是否正常。例如,您可以检查y是否为数字(使用appropriate function):

parseMessage (x:y:z)
  | x == 'I' && isDigit y = LogMessage Info (read [y]) (unwords [z])
  ...

或者,您可以使用readMaybe中的Text.Read read,但如果失败则不会抛出异常,而是返回任何值:

parseMessage (x:y:z)
  | x == 'I', Just n <- readMaybe [y] = LogMessage Info n (unwords [z])

答案 1 :(得分:0)

问题是您的输入消息格式。您正在以字符串形式读取一行,然后匹配字符串中的字符(因为字符串是[Char]的类型别名)。 在sample.log中,第一行(I 6 Completed armadillo processing)将作为字符串传递给parseMessage,参数将采用以下值:

x = 'I'

y = ' ' --single white space character

z = "6 Completed armadillo processing"

read获取空格字符并抛出*** Exception: Prelude.read: no parse

要获取值,您可以执行以下操作:

    parseMessage :: String -> LogMessage
    parseMessage msg = 
      case words msg of
        "I":y:z -> LogMessage Info (read y :: TimeStamp) (unwords z)
        "W":y:z -> undefined
        "E":y:z -> undefined
        _       -> undefined

这样可以轻松提取前两个有效字词(在这种情况下为MessageTypeTimeStamp)。