如何用逗号代替小数点来解析浮点数?

时间:2015-07-11 14:46:23

标签: parsing haskell parsec

我想从使用逗号作为小数分隔符存储它们的文件中解析Float个值。因此,我需要一个函数myParse :: String -> Float,例如,myParse "23,46" == 23.46

我对如何做到这一点有一些想法,但它们似乎都过于复杂,例如:

  • ,替换为字符串中的.并使用read;或
  • 关注Native SQL,挑战单态限制的诅咒。

有更简单的方法,还是我真的需要使用解析库?在第二种情况下,你可以粘贴一些建议,以便让我开始吗?单态限制让我害怕,我相信必须有一种方法可以在不使用语言扩展的情况下完成此操作。

1 个答案:

答案 0 :(得分:6)

,替换.,然后致电read就行了;你只需要记住使用你自己的专用函数而不是普通的read

readFloatWithComma :: String -> Float
readFloatWithComma = read . sanitize
  where
    sanitize = map (\c -> if c == ',' then '.' else c)

在GHCi中:

λ> readFloatWithComma "23,46"
23.46

关于parsec方法,尽管the article you link to suggest,只要您拥有所有顶级绑定的类型签名,单态限制就不必担心了。特别是,以下代码不需要任何语言扩展来正确编译(至少在GHC 7.10.1中):

import Text.Parsec
import Text.Parsec.String         ( Parser )
import Control.Applicative hiding ( (<|>) )

infixr 5 <++>
(<++>) :: Applicative f => f [a] -> f [a] -> f [a]
a <++> b = (++) <$> a <*> b

infixr 5 <:>
(<:>) :: Applicative f => f a -> f [a] -> f [a]
a <:>  b = (:) <$> a <*> b

number :: Parser String
number = many1 digit

plus :: Parser String
plus = char '+' *> number

minus :: Parser String
minus = char '-' <:> number

integer :: Parser String
integer = plus <|> minus <|> number

float :: Parser Float
float = fmap rd $ integer <++> decimal <++> exponent
    where rd       = read :: String -> Float
          decimal  = option "" $ ('.' <$ char ',') <:> number
          exponent = option "" $ oneOf "eE" <:> integer

在GHCi中:

λ> parseTest float "23,46"
23.46