2

私はhaskellを学んでいて、現在文字列から整数と浮動小数点数を解析しようとしています。

ただし、「342」または1つ以上の非数字文字を含まない「数値」で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タプルの2番目の要素として空のリストを返す場合のケースを処理するためのより良い方法はありますか?

-ありがとう

4

1 に答える 1

6

"342"thenspan 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"
                     _ -> .... 

私はばかげたエラーメッセージを出しましたが、明らかにもっと賢明なコードをそこに書くべきです。

于 2013-02-03T08:12:29.733 に答える