每当我使用双精度和整数编写函数时,我发现这个问题,我不断在我的函数中到处使用'fromIntegral'。例如:
import Data.List
roundDouble
:: Double
-> Int
-> Double
roundDouble x acc = fromIntegral (round $ x * 10 ** fromIntegral acc) / 10 ** fromIntegral acc
有没有更简单的方法来写这个? (我知道可能有更简单的方法来舍入一个数字,如果有,请告诉我!但我主要感兴趣的是如何避免使用这么多'fromIntegrals'。)
谢谢,Ash
答案 0 :(得分:24)
有时候我发现辅助函数很有用:
roundDouble x acc = (round $ x * 10 ^ acc) /. (10 ^ acc)
where
x /. y = fromIntegral x / fromIntegral y
也可以写出辅助函数:
(/.) = (/) `on` fromIntegral
on
来自Data.Function
。
答案 1 :(得分:12)
您可以使用^
代替**
。 ^
将任何积分作为第二个参数,因此您无需在第二个操作数上调用fromIntegral
。所以你的代码变成了:
roundDouble x acc = fromIntegral(round $ x * 10 ^ acc)/ 10 ^ acc
只有一个fromIntegral
。那个你无法摆脱的round
自然会返回一个积分,你不能对积分进行非整数除法。
答案 2 :(得分:6)
我在编组代码方面遇到了类似的问题,其中fromIntegral
用于将CInt转换为Int。我通常定义fI = fromIntegral
以使其更容易。您可能还需要为其提供显式类型签名或使用-XNoMonomorphismRestriction。
如果你正在做大量的数学运算,你可能想看看Numeric Prelude,它似乎在不同的数字类型之间有更明智的关系。
答案 3 :(得分:4)
另一个想法,类似于luqui's。我对fromIntegral
的大部分问题都与Int
或Double
除Double
的必要性有关。因此,此Int
允许划分任何两种(/.)
类型,不一定相同,不一定是{lu}的解决方案中的Real
类型:
Integral
示例:
(/.) :: (Real a, Real b, Fractional c) => a -> b -> c
(/.) x y = fromRational $ (toRational x) / (toRational y)
它适用于任何两个ghci> let (a,b,c) = (2::Int, 3::Double, 5::Int)
ghci> (b/.a, c/.a, a/.c)
(1.5,2.5,0.4)
,但我怀疑合理划分和转换为Real
并不是非常有效。
现在你的例子变成了:
Rational