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,它会将其视为错误输入 - 为什么?在我的代码中,IntInteger 的出现次数为零。我只使用Num,因为我想接受任何类型的数字。

如果我明确地将其称为getNum "Enter a number: " :: IO Double,那么它可以工作。我必须这样做吗? Haskell 的类型系统是否只是在欺骗我认为我应该能够做到这一点,而实际上如果没有完整的动态类型是不可能的?如果是这样,那么为什么我的代码甚至可以编译;为什么它假设整数?

【问题讨论】:

文体小注:使用模式匹配比isNothingfromJust更好,所以if表达式可以替换为case input of Nothing -&gt; getNum s; Just x -&gt; return x 谢谢,看起来好多了。 【参考方案1】:

您的函数确实会接受IntegerFloat 或任何其他Num 实例。但是,它接受哪种类型,以及它如何解析String,并不是由它接收的输入决定,而是由结果应该是什么类型决定取决于你用它做什么。

假设您使用getNum 并将结果值传递给需要Float 的东西;在这种情况下,它将解析一个Float 值。如果你将它传递给需要 Integer 的东西,它会解析它。

至于为什么它假定Integer,对于模糊类型specified in the Haskell Report,有一个“默认”系统,并且规则说具有Num 约束的模糊类型应该默认为Integer

【讨论】:

好的,所以我想在我的示例中,当我调用 getNum 时,我必须添加 :: (Fractional a, Read a) =&gt; IO a 以允许小数(我不想明确指定浮点数或双精度数)。 是的,但请注意,添加 Fractional 约束将限制它接受 onlyFractional 实例,因此您将无法将其用于其他以这种方式输入。大多数情况下,在实际程序中,您会知道需要的特定类型,因此通常没有理由限制事物,除了在 GHCi 中进行测试之类的东西。 我没有将它添加到实际函数中,我在使用函数时将其添加为类型注释。我不太确定我是否理解你在最后一句中所说的话——在 Haskell 代码中用于泛化函数的类型类约束不是无处不在吗? 啊。对不起,我看错了。无论如何,我所说的是在实践中很少需要添加 extra 约束或显式类型注释,因为最终您会将getNum 的输出传递给需要特定类型的东西,然后键入推理将从那里处理它。 我已经把它改成了那个,我也只是使用default (Double)而不是那个长类型注释,因为这是一个非常小的模块,我认为这样更合乎逻辑。

以上是关于Haskell:读取一个数字(整数或浮点数)的主要内容,如果未能解决你的问题,请参考以下文章

ruby 转换由浮点分隔的逗号分隔的数字整数或浮点数

将 strlen() 与数组整数或浮点数一起使用 [重复]

可以采用整数或浮点数或双精度数或任何其他可转换为浮点数的 C++ 函数

android中TextView能直接显示整数或浮点数吗?

正则表达式从逗号分隔列表中删除连续重复(整数和/或浮点数)

将具有 1.185 亿欧元或 6 万欧元等货币值的 pandas 列转换为整数或浮点数 [关闭]