我正在学习Haskell,并且我一直在编写一些非常简单的程序来练习。其中一个程序就是我所贬低的程序:
import System.IO
main = do
putStrLn "Give me year: "
y <- getLine
let res = show . calcPop $ read y
putStrLn ("Population in " ++ y ++ " will be " ++ res)
pop :: Float
pop = 307357870.0
secInYear :: Float
secInYear = 365.0 * 24.0 * 60.0 * 60.0
bRate :: Float
bRate = secInYear / 7.0
dRate :: Float
dRate = secInYear / 13.0
iRate :: Float
iRate = secInYear / 35.0
calcPop :: Float -> Float
calcPop year = let years = year - 2010 in (years*bRate + years*iRate + pop - years*dRate)
它的作用是在2010年之后花一年时间来计算当年的估计人口数量,现在它正常工作并且所有情况除外,因为您可能已经注意到每个单独的数字被投射为浮点数。现在这样做是非常荒谬的,因为没有理由让当前的人口,一年或一年中的秒数本身就不算什么,不幸的是,虽然当我这样做时我得到了编译器/
函数的错误说明了一些关于小数int和*
函数的错误,说它推断浮点数作为第一个参数。现在我已经理解Haskell在遇到涉及int和float的操作时会像其他语言一样只会改变int,就像浮动一样,这里并没有发生。有人可以解释为什么我会得到这些错误以及如何获得整合和浮动以进行合作,因为显然我仍然没有足够好地掌握Haskell类型系统来自己做这件事吗?
答案 0 :(得分:9)
Haskell类型严格;除非整数文字自动包含在fromIntegral
中,否则永远不会自动为您转换类型。相反,当您只需要处理`div`
/ Int
时,您可能希望使用更适合类型的操作,例如Integer
,并fromIntegral
来提升Float
需要时,或Double
。
(语法注释:`function`
将前缀函数转换为中缀运算符。)
答案 1 :(得分:2)
对于Haskell中的整数除法,您可以使用div
或quot
。
答案 2 :(得分:2)
整数文字表示 应用该功能 fromInteger到适当的值 类型为Integer。同样,一个浮动 point literal代表an 将fromRational应用于一个值 Rational类型(即Ratio。) 整数)。
这意味着源代码中的“7”变为“(来自输入器7)”,“1.5”变为“(来自全国(3比率。%2))”。诸如(+)和(/)之类的数字运算具有类似“a-> a-> a”的类型签名,这意味着它们是完全相同类型的两个参数并返回与给定相同的类型。这些标准操作符永远不能执行诸如向Int添加Float之类的操作。您可以编写一个(fromIntegral)来尝试将类似Int的类型提升为Double或Float之类的东西。