haskell的read
在浮点数上有点严格:
$ ghci
GHCi, version 8.2.2: http://www.haskell.org/ghc/ :? for help
Prelude> read "-1E34" :: Double
-1.0e34
Prelude> read "-1.E34" :: Double
*** Exception: Prelude.read: no parse
Prelude>
是否有接受第二种形式的读版?它在物理科学中很普遍。例如,fortran读写并写下了这些形式。
Haskell不支持的另一个示例是" 0.1"。这个更常见。我只是不想转换输入ASCII文件。。。。
这是使用MegaparSec的自定义解析器。
import Text.Megaparsec
import Text.Megaparsec.Char
realLiteral :: (MonadParsec e s m, Token s ~ Char) => m Double
realLiteral = mkFloat <$> sign <*> intgPart <*> fracPart <*> exponent
where mkFloat sgn itg frc expn
= fromIntegral sgn * (fromIntegral itg + frc) * 10^^expn
sign = (-1) <$ char '-'
<|> 1 <$ char '+'
<|> pure 1
intgPart = read . ('0':) <$> many digitChar
fracPart = char '.' *> (toFrc<$>many digitChar)
<|> pure 0
where toFrc "" = 0
toFrc digits = read digits / 10^length digits
exponent = oneOf "eEdD" *> ((*) <$> sign <*> (read<$>some digitChar))
<|> pure 0
[1 of 1]编译主(wtmpf-file5764.hs,解释(好的,加载了1个模块。*主> parsemaybe realiteral" 1"只有1.0*main> parsemaybe realiteral" -3"Just(-3.0(*main> parsemaybe realiteral" -9e 2"Just(-900.0(*main> parsemaybe realiteral" .3e 9"只有3.0E8*main> parsemaybe realiteral" -1.e34"Just(-1.00000000000001E34(*Main> Parsemaybe Realiteral" -1.673986E-40"Just(-1.673985999999999E-40(*main> parsemaybe realiteral" -3.e 16"Just(-3.0E16(
正如某人所说,您可以创建一个辅助功能(或三个(,以帮助将数字转换为与read
一起使用的格式。我不是Haskell最好的,所以我不确定还有哪些其他解决方案,但是我写了一些功能来提供帮助。我已经用read
进行了测试,到目前为止,一切似乎都很好。
prefixZero :: String -> String
prefixZero "" = ""
prefixZero ('-' : xs) = '-' : '0' : xs
prefixZero s = '0' : s
suffixZero :: String -> String
suffixZero "" = ""
suffixZero ('.' : exp@('E' : _)) = '.' : '0' : exp
suffixZero (x : xs) = x : suffixZero xs
format :: String -> String
format = suffixZero . prefixZero
您可以调用以下内容:
read (format "-1.E34") :: Double
输出以下输出:
-1.0e34