翻阅“自学......”一书,我遇到了一个BMI计算器应用程序。到目前为止,该应用程序采用Double对列表并返回Double列表:
calcBMI :: [(Double, Double)] -> [Dobule]
calcBMI xs = [bmi w h | (w, h) <- xs]
where bmi weight height = weight / height ^ 2
尝试将另一个函数应用于返回列表的每个元素我尝试了map declareBMI head calcBMI [(w, h) | w <- [60..70], h <- [1.65]]
但是出现了错误(定义了declareBMI
):
declareBMI :: Double -> String
declareBMI bmi
| bmi <= 18.5 = "Skinny"
| bmi <= 25 = "Norm"
| bmi <=30 = "Overweight"
| otherwise = "OBESE!"
在查看了map
的定义(即map f x:xs = f x : map f xs
)后,我发现了问题:我正试图在 lazy head > list,意思是解释器尝试第一次运行calcBMI
,然后只有head
- 结果......这当然会失败,因为calcBMI
需要对列表。
所以,我的问题是
calcBMI
函数,以便在结果列表中运行head
?head
结果列表中的每个元素?答案 0 :(得分:1)
确保类型排列。如果您不确定类型或编译器错误,请尝试将代码分解为较小的表达式,并使用GHCi或TypedHoles来检查类型。
示例GHCi会话:
> let xs = [(w, h) | w <- [60..70], h <- [1.65]]
> :t calcBMI xs
calcBMI xs :: [Double]
我们在此处询问了calcBMI xs
的类型,并按预期获得了[Double]
。
现在我们可以使用calcBMI xs
:
head
的第一个元素
> head (calcBMI xs)
22.03856749311295
我们可以使用head
,因为它的输入是一个列表,calcBMI xs
是一个列表。
> :t head
head :: [a] -> a
declareBMI
的类型为Double -> String
,因此我们可以在普通Double
值上使用它,但我们也可以在map
列表中的值上使用它。
> let bmis = calcBMI xs
> declareBMI (head bmis)
"Norm"
我们在declareBMI
上使用了Double
。我们也可以先在列表元素上使用declareBMI
,然后再应用head
。
> :t map declareBMI bmis
map declareBMI bmis :: [String]
> map declareBMI bmis
["Norm","Norm","Norm","Norm","Norm","Norm","Norm","Norm","Norm","Overweight","Overweight"]
> head (map declareBMI bmis)
"Norm"
另外,不要忘记在Haskell中我们只使用空格来应用函数。所以head (map declareBMI bmis)
是正确的,因为map
在这里有两个参数,head
需要一个参数。我们不会为函数调用括号,而是函数的各个参数。