Haskell:读取一个数字(整数或浮点数)
Posted
技术标签:
【中文标题】Haskell:读取一个数字(整数或浮点数)【英文标题】:Haskell: read a number (Integer or Floating point) 【发布时间】:2012-03-22 00:54:04 【问题描述】:我正在使用maybeRead
的这个实现:
maybeRead :: (Read a) => String -> Maybe a
maybeRead = fmap fst . listToMaybe . filter (null . dropWhile isSpace . snd) . reads
还有我自己的 getNum
函数,它会一直提示直到获得有效输入:
getNum :: (Num a, Read a) => String -> IO a
getNum s = do
putStr s
input <- fmap maybeRead getLine
if isNothing input
then getNum s
else return $ fromJust input
但是,如果我输入 5.2
,它会将其视为错误输入 - 为什么?在我的代码中,Int
和 Integer
的出现次数为零。我只使用Num
,因为我想接受任何类型的数字。
如果我明确地将其称为getNum "Enter a number: " :: IO Double
,那么它可以工作。我必须这样做吗? Haskell 的类型系统是否只是在欺骗我认为我应该能够做到这一点,而实际上如果没有完整的动态类型是不可能的?如果是这样,那么为什么我的代码甚至可以编译;为什么它假设整数?
【问题讨论】:
文体小注:使用模式匹配比isNothing
和fromJust
更好,所以if
表达式可以替换为case input of Nothing -> getNum s; Just x -> return x
。
谢谢,看起来好多了。
【参考方案1】:
您的函数确实会接受Integer
、Float
或任何其他Num
实例。但是,它接受哪种类型,以及它如何解析String
,并不是由它接收的输入决定,而是由结果应该是什么类型决定取决于你用它做什么。
假设您使用getNum
并将结果值传递给需要Float
的东西;在这种情况下,它将解析一个Float
值。如果你将它传递给需要 Integer
的东西,它会解析它。
至于为什么它假定Integer
,对于模糊类型specified in the Haskell Report,有一个“默认”系统,并且规则说具有Num
约束的模糊类型应该默认为Integer
。
【讨论】:
好的,所以我想在我的示例中,当我调用getNum
时,我必须添加 :: (Fractional a, Read a) => IO a
以允许小数(我不想明确指定浮点数或双精度数)。
是的,但请注意,添加 Fractional
约束将限制它接受 only 的 Fractional
实例,因此您将无法将其用于其他以这种方式输入。大多数情况下,在实际程序中,您会知道需要的特定类型,因此通常没有理由限制事物,除了在 GHCi 中进行测试之类的东西。
我没有将它添加到实际函数中,我在使用函数时将其添加为类型注释。我不太确定我是否理解你在最后一句中所说的话——在 Haskell 代码中用于泛化函数的类型类约束不是无处不在吗?
啊。对不起,我看错了。无论如何,我所说的是在实践中很少需要添加 extra 约束或显式类型注释,因为最终您会将getNum
的输出传递给需要特定类型的东西,然后键入推理将从那里处理它。
我已经把它改成了那个,我也只是使用default (Double)
而不是那个长类型注释,因为这是一个非常小的模块,我认为这样更合乎逻辑。以上是关于Haskell:读取一个数字(整数或浮点数)的主要内容,如果未能解决你的问题,请参考以下文章