Haskell或Standard ML适合初学者?
我将要教授一个分立结构的低级课程。 我选择了离散结构,逻辑和可计算性的教科书,部分原因是它包含有助于使用函数式编程语言实现的示例和概念。 (我也认为这是一本很好的教科书。)
我想要一个易于理解的FP语言来说明DS概念,并且学生可以使用。 充其量,大多数学生在Java中只有一两个学期的程序设计。 看过Scheme,Erlang,Haskell,Ocaml和SML之后,我已经选择了Haskell或Standard ML。 我倾向于Haskell,原因如下,但我希望那些积极参与其中的程序员的意见。
实质上,SML和Haskell大致相同。 我倾向于Haskell,因为我热爱Haskell中的列表理解和无限列表。 但是我担心Haskell紧凑语法中大量符号可能会导致学生出现问题。 从我读过的其他文章中可以看到,Haskell不推荐用于FP的初学者。 但是我们不打算构建完整的应用程序,只是尝试简单的算法。
你怎么看?
编辑:在阅读你的一些很好的回应后,我应该澄清我的一些要点。
在SML中,在解释器中定义函数和在外部文件中定义函数之间没有语法区别。 假设你想写出阶乘函数。 在Haskell中,你可以将这个定义放入一个文件并加载到GHCi中:
fac 0 = 1
fac n = n * fac (n-1)
对我而言,这很清晰,简洁,并且符合书中的数学定义。 但是,如果您想直接在GHCi中编写函数,则必须使用不同的语法:
let fac 0 = 1; fac n = n * fac (n-1)
在使用交互式口译员时,从教学的角度来看,当学生可以在文件和命令行中使用相同的代码时,它非常非常方便。
通过“明确确认函数”,我的意思是说,在定义函数时,SML马上就会告诉你函数的名字,参数的类型和返回类型。 在Haskell中,你必须使用:type
命令,然后你会得到令人困惑的咖喱记号。
关于Haskell更酷的一件事 - 这是一个有效的函数定义:
fac 0 = 1
fac (n+1) = (n+1) * fac n
再次,这符合他们在教科书中可能找到的定义。 不能在SML中做到这一点!
就像我喜欢Haskell一样,下面是我喜欢SML在离散数学和数据结构(以及大多数其他初学者课程)中的一个类的原因:
Haskell程序的时间和空间成本可能很难预测,即使对于专家来说也是如此。 SML提供了更多有限的方法来吹机。
交互式解释器中的函数定义语法与文件中使用的语法相同,因此您可以剪切和粘贴。
尽管SML中的运算符重载完全是虚假的,但它也很简单。 在Haskell中教授整个课程而不必进入类型班是很困难的。
学生可以使用print
来调试。 (尽管正如一位评论者指出的那样,使用Debug.Trace.trace
在Haskell中获得几乎相同的效果。)
无限的数据结构打击了人们的思想。 对于初学者来说,最好让他们定义一个完整的参考单元格和thunk的流类型,以便他们知道它是如何工作的:
datatype 'a thunk_contents = UNEVALUATED of unit -> 'a
| VALUE of 'a
type 'a thunk = 'a thunk_contents ref
val delay : (unit -> 'a) -> 'a thunk
val force : 'a thunk -> 'a
现在它不再是魔术了,你可以从这里到流(无限列表)。
布局并不像Python中那么简单,可能会让人困惑。
Haskell有两个地方有优势:
在核心Haskell中,您可以在其定义之前编写函数的类型签名。 这对学生和其他初学者非常有用。 在SML中处理类型签名并不是一个好方法。
Haskell具有更好的具体语法。 Haskell语法是对ML语法的重大改进。 我写了一篇关于何时在ML计划中使用括号的简短说明; 这有点帮助。
最后,有一柄双刃剑:
do
记号,并return
是令人困惑的。 关于相关主题,以下是您的课程准备建议:不要忽视Chris Okasaki的纯功能数据结构。 即使你没有你的学生使用它,你一定会想要一个副本。
我们在我们大学教授哈斯克尔大学的第一年。 我对此的感觉有点混杂。 一方面,Haskell第一年教学意味着他们不必忘记命令式的风格。 Haskell也可以生成非常简洁的代码,以前有一些Java的人可以欣赏。
我注意到学生经常会遇到的一些问题:
起初,模式匹配可能有点困难。 学生们最初看到价值构造和模式匹配是如何相关的,有些问题。 他们也有一些区分抽象的问题。 我们的练习包括编写简化算术表达式的函数,一些学生很难看到抽象表示(例如Const 1
)和元语言表示( 1
)之间的差异。
此外,如果您的学生本身应该编写列表处理函数,请小心指出模式之间的差异
[]
[x]
(x:xs)
[x:xs]
根据你想要在途中教他们多少功能性编程,你可以给他们一些库函数,让他们玩弄它。
我们没有向我们的学生讲授匿名函数,我们只是告诉他们有关where
子句。 对于某些任务来说,这有点冗长,但在其他方面效果不错。 我们也没有告诉他们有关部分申请; 这可能很容易在Haskell中解释(由于它的书写类型),所以它可能值得向他们展示。
他们很快发现了列表zipWith
,并优先考虑高阶函数,如filter
, map
, zipWith
。
我想我们错过了一些教他们如何让他们引导他们的想法的类型。 不过,我不确定这是否对初学者有帮助。
错误消息通常对初学者不是很有帮助,他们可能偶尔需要一些帮助。 我自己并没有尝试过,但有一个Haskell编译器专门针对新手,主要通过更好的错误消息:氦气
对于小型项目来说,可能的空间泄漏等问题不是问题。
总体而言,Haskell是一门很好的教学语言,但有一些缺陷。 鉴于学生对列表理解的感觉比高阶函数更舒适,这可能是您需要的论证。 我不知道你的课程时间有多长,或者你想要教他们多少节目,但是要花点时间教他们基本的概念 - 他们会需要它。
顺便说一句,
#SML有一个真正的交互式解释器,可以在其中定义和使用函数。 在Haskell中,函数必须在单独的文件中定义并在用于交互式shell之前进行编译。
不准确。 使用GHCi:
Prelude> let f x = x ^ 2
Prelude> f 7
49
Prelude> f 2
4
Haskell在教育方面也有很好的资源。 页面,有来自不同教师的经验。 http://haskell.org/haskellwiki/Haskell_in_education
最后,如果你使用Haskell,你将能够教给他们多核并行:
链接地址: http://www.djcxy.com/p/43317.html上一篇: Haskell or Standard ML for beginners?
下一篇: Haskell: Composition of morphisms in monoidal categories