mag*_*mig 1 haskell boolean ghci
我的课程是通过这样的输入来总结9级以上(从0到20)的学生数量:
aprov [("John",14)("Martha",8)("Elsa",12)]
Run Code Online (Sandbox Code Playgroud)
输出应为"2".但在编译时:
k = 0
aprov [] = 0
aprov ((a,n):y) = if n > 9 then k == k + 1 else k == k
Run Code Online (Sandbox Code Playgroud)
GHCi给了我这个错误:
Could not deduce (Num Bool) arising from the literal `0'
from the context (Num a, Ord a)
bound by the inferred type of
aprov :: (Num a, Ord a) => [(t, a)] -> Bool
at prog.hs:(29,1)-(30,55)
Possible fix: add an instance declaration for (Num Bool)
In the expression: 0
In an equation for `aprov': aprov [] = 0
Run Code Online (Sandbox Code Playgroud)
我该怎么做才能解决它.顺便说一句,我怎样才能限制"n"以使最大值为20?
感谢您的帮助!
问题是你指定
aprov [] = 0
Run Code Online (Sandbox Code Playgroud)
然后在下一行你说
aprov ((a,n):y) = if n > 9 then k == k + 1 else k == k
Run Code Online (Sandbox Code Playgroud)
返回两个表达式中的一个
k == k + 1
Run Code Online (Sandbox Code Playgroud)
要么
k == k
Run Code Online (Sandbox Code Playgroud)
哪个是布尔.所以编译器认为你的函数必须返回一个Bool,但你也有它返回0,这是一个Num a => a,而Bool不是一个Num.
在这种情况下,您说您想要计算其成绩通过特定考试的学生(>9).好吧,在Haskell中,所有值都是不可变的,你不能从它们的初始值改变它们.这很难,我们习惯于能够修改变量,但在Haskell 中没有变量.
相反,我们可以使用函数来执行我们通常使用变量的操作.因此,让我们列出问题陈述以及我们可以采取的步骤:
计算9年级以上的学生人数
我们可以通过以下步骤解决这个问题
让我们解决第一步:
-- A simple type alias to make our type signatures more readable
-- This just says that "Student" and "(String, Int)" are interchangeable
type Student = (String, Int)
withMinGrade :: Int -> [Student] -> [Student]
withMinGrade minGrade [] = []
withMinGrade minGrade ((name, grade):rest) =
if grade > minGrade
then (name, grade) : withMinGrade minGrade rest
else withMinGrade minGrade rest
Run Code Online (Sandbox Code Playgroud)
所以我们在这里说,如果我们要求哪个学生从空列表中获得最低成绩,我们会得到一个空列表.如果列表中至少有一名学生,我们会根据允许的最低成绩检查他们的成绩,如果它超过了我们将其返回以及对其他学生执行相同的操作,否则我们只检查其余的学生.如果这看起来像很多工作,那是因为它!Haskell内置了一个方便的函数来执行这个精确的操作filter.看起来像
filter :: (a -> Bool) -> [a] -> [a]
filter condition [] = []
filter condition (x:xs) =
if condition x -- Apply the function "condition" to "x" returning a Bool
then x : filter condition xs
else filter condition xs
Run Code Online (Sandbox Code Playgroud)
注意这与基本相同withMinGrade,但是可以推广到任何条件.使用filter,我们可以withMinGrade更简单地实现:
withMinGrade :: Int -> [Student] -> [Student]
withMinGrade minGrade students = filter checkStudent students
where checkStudent (name, grade) = grade > minGrade
Run Code Online (Sandbox Code Playgroud)
我们也可以使用内联lambda函数来做到这一点,所以我们不必定义checkStudent:
withMinGrade minGrade students = filter (\(name, grade) -> grade > minGrade) students
Run Code Online (Sandbox Code Playgroud)
甚至还有一些有趣的功能组合:
withMinGrade minGrade students = filter ((> minGrade) . snd) students
Run Code Online (Sandbox Code Playgroud)
我会让你玩这个定义来弄清楚它是如何工作的
现在解决问题2.这个使用类似的递归方式,但我们返回一个数字而不是一个列表:
-- count should work on any kind of list
count :: [a] -> Int
count [] = 0
Run Code Online (Sandbox Code Playgroud)
所以这种情况很容易,空列表中有0个元素.具有至少一个元素的列表怎么样?嗯,直观地说,我们希望它返回的计数大于列表其余部分的长度,或者使用代码
count :: [a] -> Int
count [] = 0
count (x:xs) = 1 + count xs
Run Code Online (Sandbox Code Playgroud)
很简单,我们说列表中的元素数量只比列表尾部的元素数量多1个.同样,Haskell有一个内置函数(更高效)length,我们可以使用它来代替!这是一个替代品的下降count.
如此结束,我们可以将这两个功能结合起来,withMinGrade并length编写我们想要的功能,但我会把这一步留作家庭作业.由于这是您的第一个Haskell程序,我还将指导您学习一本Haskell,这是一本非常容易阅读的书,我曾经开始使用这种有趣而强大的语言.它将向您展示许多示例,并提供有关Haskell如何工作的大量解释,以及如何在不需要再次修改变量的情况下进行常规编程!一开始很难"获得",但是一旦你拥抱不变性,你会希望你在C/C++/Python/Java/.NET/Ruby/Bash/Javascript /等中拥有它.它确实使得更容易理解代码如何工作,并确保它每次都能以这种方式工作.