乔海燕,周晓聪,杨永红
(中山大学计算机学院,广东广州 510006)
Haskell 函数程序设计基础是一门面向全校各专业的程序设计入门选修课,采用函数语言Haskell 讲授。Haskell 虽然不是业界主流语言,但具有更高的抽象层次,程序设计过程和描述更接近数学,并能使学生更专注于程序设计的基本思想和问题,因此西方许多著名高校采用该语言讲解程序设计入门[1]。事实上,设计Haskell的目的之一就是创建一种便于教授程序设计的语言。虽然目前大多数程序设计入门教学使用Python,但笔者认为从编写正确程序的角度看,Haskell 能给出更好的解。高校选择讲授的语言应该从该语言传授的思想方法是否鼓励学生编写优美正确的程序为出发点,而不是语言的流行程度。以往教学实践表明,大部分学生学完该课程后表示喜欢函数程序设计的思维方法,欣赏其表现出的简洁之美[2]。
然而,Haskell 程序设计基础课程也存在诸多问题,例如部分同学表示学习程序设计具有挑战性、难度大,涉及到的数学知识难度更大,不少学生在学习初期放弃,还有部分学生因害怕挂科而不选修该门课程。为了克服学生的惧怕心理,并进一步提高教学效果,在中山大学数字化学习平台BB(Black Board)系统上使用慕课和翻转课堂线上线下相结合的方式教学,探索Haskell 程序设计教学入门课的有效教学手段,吸引更多学生完成课程学习。
翻转课堂已广泛应用于教学实践,在激发学生学习兴趣和提高学习成绩方面取得了较好效果[3-4]。例如,何迎生等[5]针对C 语言程序设计教学中遇到的问题,提倡基于慕课的翻转课堂教学,实践显示该种教学方式提高了学生的学习积极性,改变了以往传统的被动学习模式,提高了学习效率,学生成绩也有显著提高。
目前国内使用Haskell 作为程序设计入门语言的高校并不多,即使在计算机相关专业也较少开设函数程序设计课程。不少学者认为函数程序设计可以更好地培养学生的数学能力,展示程序设计中的许多基本概念,并探讨了教学内容设计方法[6-8]。然而,对于选修课,如何通过教学内容和方法的改革吸引学生完成课程,不因课程的挑战性吓退学生,并没有许多文献或经验可供借鉴。
中山大学多年来一直开设函数程序设计基础课,供全校对计算机程序设计有兴趣的同学学习。虽然函数程序设计语言并不是业界主流,但其程序设计范式对其他程序设计语言产生了很大影响,例如许多程序设计语言都引入了λ 表达式以及支持函数式程序设计的语法和机制。早期调研显示,学习函数程序设计有利于初学者理解程序设计的基本知识,便于有一定基础的学生设计出质量更高的程序[2]。
Haskell 函数程序设计基础课程每周设置2 学时面对面教学,并在为每位学生配备了计算机的实验室中进行。该课程一直使用中山大学数字化学习平台BB 系统发布教学资源、课程信息和在线作业,但并没有课前可观看的视频资源。在教学改革前,BB 系统主要用于发布课程信息和课后作业,学生缺乏主动学习意识。为改进教学,仿照慕课教学模式,为各个教学内容板块设计和制作了屏幕教学录像,并配备了相关知识点练习,在课前上传至BB 系统,供学生观看和练习。每周2 学时的课堂由教师讲解为主转变为重点解决同学们提出的疑难问题,讲解重点和难点,同时鼓励学生相互交流,提出并回答问题。针对在课堂上不愿意提出问题和回答问题的学生,鼓励其使用电脑上安装的电子教室软件通过发送消息的方式提问或回答问题。实践证明,多数学生虽然不愿意在课堂上提问或回答问题,但他们可以接受用电子教室软件相互提问或回答问题。早期调研也显示,电子教室可以较好地增强师生互动和学生之间的互动[9]。
慕课教学研究表明,制作视频时有多个因素决定观看者的投入程度[10],6~9min 的短视频、教师的激情和较快的语速、视频与学生的交互等都能更加吸引学生的注意力。为此,本课程组制作了长度适当的短视频,编写了可供学生在线学习的题库,设计了基于BB 系统的类慕课网站[11]。
2.2.1 典型案例设计
在教学过程中通过典型案例使学生感受函数程序设计的美感,激发其学习兴趣。函数程序语言更抽象更接近数学,无需考虑与内存相关的概念,只需要在数学抽象层描述计算的逻辑。例如,著名的快速排序算法的计算逻辑用Haskell描述一目了然:
以上代码表示当输入是空列表时,计算结果也是空列表;当列表为(x:xs)时,x 是列表的第一个元素,xs 是列表的尾部,则以x 为标准,将xs 的元素划分为小于x 的列表less 和大于等于x 的列表more,然后分别对less 和more 递归排序,最后计算结果为qsort less++[x]++qsort more,其中++表示列表的串接。对于初学者来说,这种简洁清晰的描述比命令式算法容易理解得多,对命令式语言有一定基础的学生也会惊讶于这种简洁之美。
在程序设计中,列表是一类重要的数据结构,掌握列表对象的处理至关重要。为此,本课程就列表数据讲解了许多有趣且容易理解的例子,例如将图形建模为字符列表的字符画,然后设计字符画的拼接和旋转函数。通过这个案例的学习,引导学生发现函数实现过程中的共同计算模式,从而引入高阶函数这个函数程序设计的特色。高阶函数有趣且容易理解,较好地激发了学生的学习兴趣和热情,进而使其轻松掌握了相关知识。
2.2.2 惰性计算机制带来模块化方法
惰性计算是Haskell 函数程序设计的另一个特色,为程序模块化提供了便利。以牛顿—拉夫逊求平方根的迭代法为例,求非负实数r平方根的迭代公式为:
式中,x0为初值。
对于给定的误差ε,当相邻两个迭代值之差绝对值不超过ε时,迭代即可终止。为此,可以将该任务分成两个简单的子任务:①一个生产无穷迭代序列[x0,x1,x2...]的函数;②一个在该迭代序列上选择满足近似要求的函数。
任务①可以在x0上反复使用迭代函数f完成,此时:
即序列[x0,f(x0),f(f(x0)),...]可以通过高阶函数计算模式repeat 而得:repeat f a=a:repeat f(f a),由此完成第一个任务的计算:
任务②可以用within 函数实现,其不断检查列表中两个相邻值之差直至这个差值足够小:
最后,求计算误差不超过eps 的平方根近似值可以表达为within eps(repeat f x0)。
这个案例很好地展示了惰性计算的魅力:repeat 部分可生成within 需要的数据,虽然repeat 可以生成无穷序列,但是惰性计算机制只需要其生成within 部分需要的数据,一旦within 检查到符合要求的数据,计算即可终止。这种将复杂问题分解为简单问题的便利是多数命令式语言不具备的,这便是惰性计算降低复杂度的魅力。
2.2.3 由易到难刷题带来获得感
学习程序设计的基本方法是动手编写程序,使学生有获得感。为此,本课程设计开发了Haskell 程序评测网站[12],每周推出5~10 个题目供大家练习。在Matrix 系统上布置难度不等的题目,并将一个问题分成由易到难的多个题目。对于每个题目,系统测试设置了多个测试样例,通过测试样例数目给学生提交的程序打分。例如,对于归并排序的实现,首先给出归并排序方法的描述:
如果输入为空列表或只有一个元素,则输出就是输入(已经有序);
如果输入xs不空
(1)将xs在中间拆分为两个子列表xs1和xs2;
(2)将xs1 和xs2 分别排序,排序结果分别是有序列表ys1 和ys2;
(3)将有序列表ys1 和ys2 合并成一个有序列表,这便是xs 的排序结果。
然后将问题分解成两个任务:
(1)实现归并函数,将两个有序列表合并为有序列表的函数:merge::Ord a=>[a]->[a]->[a]
(2)在归并排序函数merge 基础上实现归并排序:mergeSort::Ord a=>[a]->[a]
两个任务分别完成、分别提交、分别测试。
这种由易到难循序渐进的作业评测方式大大提升了学生们的获得感,同时激发了其编写程序的热情,课堂上程序设计的讨论也多了起来,不少同学要求老师布置更多题目。使用Matrix 测评使得学生提交的代码对老师即刻可见,师生交流更畅通,便于老师有针对性地教学和指导。
在课程进行到10 周左右时进行网上问卷调查,就课程教学情况和同学反馈进行调查统计。实施翻转课堂的一个重要前提是保证学生在课前观看视频。调查结果显示,47%的学生表示每次都会在课前观看视频,39%的学生表示大部分时间会在课前观看,只有6%的学生表示很少观看,1%的学生表示基本不看。对于观看视频是否对理解课程内容有帮助,54%的学生表示很有帮助,41%的学生表示有些帮助。对于翻转课堂的感受,17%的学生表示喜欢,63%的学生表示还好,需要适应,也有7%的学生表示反对。
近4 年该课程的完课学生人数和考试成绩比较见表1。结果显示,近年来选修课人数呈增加趋势(见图1),且学生成绩呈上升趋势(见图2)。使用翻转课堂后,有更多学生完成了课程,而且平时成绩增长明显,反映出学生在平时学习过程中得到了更多帮助,因而能够坚持完成课程学习,并且投入更多精力完成作业。分析发现,2019 学年期末考试成绩低于上学年,原因可能是此次期末考试首次启用了在线评测系统,系统评测比以往考试评分更严格,要求更高。以往期末考试包括部分编写程序任务,但并没有提交到在线评测系统。
Table 1 Number of students who completed the course and their grades表1 各学期完课人数和成绩
Fig.1 Number of students who completed the course图1 各学期完成课程人数
Fig.2 Passing rate and excellence rate of students of each term图2 各学期学生成绩及格率和优秀率
开设Haskell 函数程序设计基础课程的目的是对程序设计感兴趣的同学提供入门知识。实践表明,慕课、翻转课堂和电子教室等技术手段确实能够为学习程序设计的学生提供及时帮助,增加师生交流和互动,使更多学生不再畏惧课程难度和挂科等问题,坚持完成课程学习;展示典型案例能使更多学生感受到函数程序设计的美感,有助于激发其学习兴趣;评测系统的循序渐进模式增加了学生的编程获得感,促使其更加深入学习。统计结果显示,实施线上线下相结合教学的学年,完成课程的学生人数较上学年有所增加,学生平均成绩、及格率和优秀率也比往年有较大提高,提示综合教学手段的应用能有效改善教学效果。