【问题标题】:Irrefutable pattern failed inside of Let statement无可辩驳的模式在 Let 语句中失败了
【发布时间】:2013-01-18 04:14:13
【问题描述】:

我正在学习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返回一个空列表作为元组的第二个元素时,有没有更好的方法来处理这种情况?

-谢谢

【问题讨论】:

    标签: haskell design-patterns let


    【解决方案1】:

    您收到错误是因为如果您使用像"342" 这样的简单整数,那么span isDigit "342" 就是("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"
                         _ -> .... 
    

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-10-29
      • 2012-10-22
      • 2015-12-25
      • 1970-01-01
      • 2021-07-19
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多