2

我正在学习haskell,目前正在尝试从字符串中解析整数和浮点数。

但是,当在“342”或任何没有单个或多个非数字字符的“数字”上尝试我的 readNum 函数时,ghci 会向我报告:

*例外:parse.hs:125:18-46: 模式 (i, (a : as)) 的无可辩驳的模式失败

data Token
    = IntTok Int | FloatTok Float | EOF

readNum :: String->(Token, String)
readNum [] = (EOF, [])
readNum xs = let (i, (a:as)) = span isDigit xs   --This is line 125
                in (case a of
                        ('.') -> let (j, (b:c:bs)) = span isDigit as
                                        in (if ((toLower b) == 'e' && (c == '+' || c == '-' || (isDigit c)))
                                                then (let (k, d) = span isDigit bs in (FloatTok (read (concat [i,[a],j, [b],[c],k])::Float), d))
                                                else (FloatTok (read (concat [i,[a],j])::Float), (b:c:bs)))
                        _ -> (IntTok (read i::Int), (a:as)))

span isDigit xs当返回一个空列表作为元组的第二个元素时,是否有更好的方法来处理这种情况?

-谢谢

4

1 回答 1

6

您会收到错误消息,因为如果您使用像"342"then span isDigit "342"is just这样的简单 Integer ("342",[]),则无法匹配(l,a:as)。应该始终匹配的模式称为无可辩驳的模式。正如您所发现的,let 绑定中的模式是无可辩驳的,所以...

您需要坚持在 let 绑定中始终匹配的模式。例如你可以做

readNum xs = let (i, ps) = span isDigit xs 
             in (case ps of 
                     ('.':as) -> let (j, qs) = span isDigit as in case qs of
                           b:c:bs -> if  ..........
                           _ -> error "not enough stuff after decimal number"
                     _ -> .... 

我给出了一个愚蠢的错误信息,但显然你应该在那里编写更明智的代码。

于 2013-02-03T08:12:29.733 回答