Haskell:具有值范围的搜索列表 - 需要语法

时间:2014-03-01 10:56:51

标签: haskell functional-programming

我有一个计算课堂上学生年龄的函数:

averageMarks :: [(String, Int)] -> Int
averageMarks list = sum (map snd list) `div` length(list)

即。学生= [(“Amy”,6),(“Scott”,12)] =将产生9的值。

现在我有一个函数,只要在学生列表中找到值,就会返回一个bool。

filterAverageMarks :: Int -> Class -> Bool
filterAverageMarks r (teacher, assistant, code, students)
        | elem r [averageMarks(students)]   = True
        | otherwise                         = False

这完全正常,但是,现在我正在尝试搜索范围的值;是吧,“年龄大于1岁的学生”。

现在功能的改变是:

filterAverageMarks :: Int -> Class -> Bool
filterAverageMarks r (teacher, assistant, code, students)
        | elem n [averageMarks(students)]   = True
        | otherwise                         = False
            where n >= r

这个函数不正确,但是当'n'大于或等于我给它的值时,我希望它为'n'的所有匹配返回True。 (对于这个例子,'1')。

任何有关更正此语法的帮助都将非常感谢! 谢谢,

亚历


编辑:

对不起,我不太清楚, 基本上,我有一个'类'类型:

type Class = (Teacher, Assistant, Code, Students)
type Student = [(String, Int)]   ---- Name & Age

我想写一个带有'年龄'的函数,然后显示班级的老师,其中包括所有学生的平均年龄。 我有一个不同“类”的负载列表(称为testClasses)。

所以为了解决这个问题,我已经写了上面的'averageMarks'函数,它将通过每个'class'中的学生来计算平均值。

每次'r'匹配时,filterAverageMarks应返回'True'(r =提供的'age')。

我还有另一个功能,可以通过老师过滤这些功能。

上述功能完全正常,但不是为每个班级返回True,而是与所提供的年龄相匹配的平均年龄。我想为每个年龄等于或大于所提供年龄的年龄返回True。

我希望你能提供帮助, 谢谢, 亚历克斯./

1 个答案:

答案 0 :(得分:1)

第一个:我不确定我是否正确理解你的功能。如果他们应该采取与我假设不同的事情,请告诉我。

让我们首先对您的代码进行一些“重构”:

在Haskell中,我们不会将参数列表括在括号中,就像在其他语言中一样。所以

averageMarks list = sum (map snd list) `div` length list

更加惯用。

继续你的第二个功能。

我想你想编写一个函数来检查一个学生是否具有完全平均分数(例如,你可以用这个谓词过滤所有学生吗?)。

您这样做是首先计算所有学生的平均成绩,然后将此单个值放入列表中,然后查看r是否在此列表中。如果 r 等于此元素,则elem通过检查每个元素来执行此操作,此行与“ r 等于平均等级”完全相同。因此,您可以将此行更改为

| r == averageMark students = True

另一个不理想的事情是你正在检查一个已经给你一个布尔值的条件来决定你是否应该返回 True False 。那么为什么不直接使用这个值:

filterAverageMarks :: Int -> Class -> Bool
filterAverageMarks r (teacher, assistant, code, students) = r == averageMark students

最后一次重构:您从不使用教师助手代码。您可以通过 _ 替换这些变量来明确这一点。所以你的代码变成了:

filterAverageMarks :: Int -> Class -> Bool
filterAverageMarks r (_, _, _, students) = r == averageMark students

现在我们终于看看你真正的问题了。

你想要做的是检查平均成绩是否大于或等于你给定的成绩 r (我希望我在这里正确理解你的意图)。

错误在于

where n >= r

我认为您正在尝试使用以下内容:让 n 为大于或等于 r 的所有值。 这不是什么地方。其中绑定用于声明仅对附加到的函数可见的函数。因此,您只需要在一个函数中使用辅助函数,而不是在全局命名空间中发挥作用。

如果您想以这种方式寻求解决方案,您可以构建一个无限列表,所有n> = r,但我建议不要这样做。

相反,我建议你在第二个函数中进行重构。通过直接比较替换小册子和elem。在应用与之前相同的重构之后,你应该得到:

filterAverageMarks :: Int -> Class -> Bool
filterAverageMarks r (_, _, _, students) = r <= averageMark students

这应该可以胜任。

我希望我能帮助你并理解你。