使用 Haskell 秒差距解析浮点数

Parsing floating point numbers with Parsec of Haskell

有一些代码用于运行解析计算器输入(整数和浮点):

import Text.Parsec hiding(digit)
import Data.Functor

type Parser a = Parsec String () a

digit :: Parser Char
digit = oneOf ['0'..'9']

fp_char :: Parser Char
fp_char = oneOf ['.', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9']

number :: Parser Integer 
number = read <$> many1 digit

fp_number :: Parser Double
fp_number = read <$> many1 fp_char

addition :: Parser Integer
addition = do
    lhv <- number
    spaces
    char '+'
    spaces
    rhv <- number
    return $ lhv + rhv

fp_addition :: Parser Double
fp_addition = do
    lhv <- fp_number
    spaces
    char '+'
    spaces
    rhv <- fp_number
    return $ lhv + rhv

显然,一旦输入了前面或后面有“.”的浮点数,这将引发异常。分别没有任何数字 before/after 点字符。如何约束字符串评估以防止执行失败?

fp_number  :: Parsec String () Double
fp_number  = read <$> parser  where 
   parser = (++) <$> number <*> (option "" $ (:) <$> char '.'  <*> number )

旁注,不要忘记处理负数。

type Parser a = Parsec String () a

digit :: Parser Char
digit = -- same 

number :: Parser String 
number =  many1 digit

fp_number  :: Parser  Double
fp_number  = read <$> parser  where 
   parser = (++) <$> number <*> (option "" $ (:) <$> char '.'  <*> number )

fp_addition :: Parser Double
fp_addition = --same

test = parseTest fp_addition "2.123 + 213.12"