我将在离散结构中教授低级课程.我选择了教科书" 离散结构,逻辑和可计算性",因为它包含有助于使用函数式编程语言实现的示例和概念.(我也认为这是一本很好的教科书.)
我想要一个易于理解的FP语言来说明DS概念以及学生可以使用的.大多数学生最多只能用一到两个学期的Java编程.在查看Scheme,Erlang,Haskell,Ocaml和SML之后,我已经确定了Haskell或Standard ML.由于下面列出的原因,我倾向于Haskell,但我喜欢那些活跃的程序员在一个或另一个的意见.
从本质上讲,SML和Haskell大致相同.我倾向于Haskell,因为我喜欢Haskell中的列表理解和无限列表.但我担心Haskell紧凑语法中的大量符号可能会导致学生出现问题.从我收集到的关于SO的其他帖子开始,Haskell不建议初学者从FP开始.但我们不打算构建成熟的应用程序,只是尝试简单的算法.
你怎么看?
编辑:在阅读了一些很棒的回复后,我应该澄清一些我的要点.
在SML中,在解释器中定义函数和在外部文件中定义函数之间没有语法上的区别.假设您要编写阶乘函数.在Haskell中,您可以将此定义放入文件中并将其加载到GHCi中:
fac 0 = 1
fac n = n * fac (n-1)
Run Code Online (Sandbox Code Playgroud)
对我来说,这很清楚,简洁,并且符合书中的数学定义.但是如果你想直接在GHCi中编写函数,你必须使用不同的语法:
let fac 0 = 1; fac n = n * fac (n-1)
Run Code Online (Sandbox Code Playgroud)
在使用交互式口译员时,从教学角度来看,当学生在文件和命令行中使用相同的代码时,非常非常方便.
通过"显式确认函数",我的意思是在定义函数时,SML立即告诉您函数的名称,参数的类型和返回类型.在Haskell中你必须使用:type
命令,然后你会得到一些有点令人困惑的咖喱符号.
关于Haskell的一个更酷的事情 - 这是一个有效的函数定义:
fac 0 = 1
fac (n+1) = (n+1) * fac n
Run Code Online (Sandbox Code Playgroud)
同样,这与他们可能在教科书中找到的定义相匹配.在SML中无法做到这一点!
众所周知,Haskell风格的类型类和ML风格的模块提供了不同的指定接口的机制.它们(可能)具有相同的功率,但实际上每种都有其自身的优点和缺点.
由于我在语言功能方面有点像包容性,我的问题是:在Haskell中添加ML样式模块有哪些主要的理论上的困难?我对以下几行的答案感兴趣:
现有的类型系统功能与ML型模块的交互性很差?(不良交互的一个例子是GADT和功能依赖,即使fundeps在技术上等同于相关类型!)
为了编译ML样式的模块,必须在编译器端放弃什么?
ML样式模块如何与类型推断交互?
相关阅读:
我一直在尝试向几个人解释switch语句和模式匹配(F#)之间的区别,但我还没有真正解释它.大多数时候他们只是看着我说"为什么你不只是使用if..then..else".
你会如何向他们解释?
编辑!感谢大家的精彩答案,我真的希望能够标出多个正确的答案.
我开始学习标准ML,现在我尝试使用新泽西标准ML编译器.
现在我可以使用交互式循环,但是如何将源文件编译为独立的可执行文件?
例如,在C中,人们可以写
$ gcc hello_world.c -o helloworld
然后运行helloworld二进制文件.
我阅读了SML NJ编译管理器的文档,但它没有任何明确的例子.
另外,是否有另一个SML编译器(允许独立二进制创建)可用?
我的问题是,标准ML的模块系统和OCaml模块系统之间是否有任何区别?OCaml是否有所有对仿函数,归属等的支持...... SML有哪些?
ML模块系统是数据抽象的编程语言支持的高水准标记.但是,从表面上看,似乎可以很容易地在支持抽象类型成员的面向对象语言中进行编码.例如,我们可以在Scala中编码SML模块系统的元素,如下所示:
是否有任何重要的功能,如编码会错过?任何可以在SML模块中表达的编码都无法表达的东西?SML使得这种编码无法做出的任何保证?
这个问题始于
SML.NET可以做仿函数并使用Microsoft .NET.
*请参阅:SML.NET用户指南第4.8.2节类类型和仿函数?
由于Microsoft .NET的一些限制,我一直看到F#无法做真正的仿函数.
*ML仿函数可以用.NET完全编码(C#/ F#)吗?
*算子的任何解决方法?
那么如果SML.NET可以在.NET上运行仿函数那么为什么F#不能呢?SML.NET做了什么,F#不能做什么?
我越了解来自类别理论的仿函数,我越看到它们的美丽,并希望在F#中拥有它们.
编辑
有人可以解释一下,这个警告意味着什么?
stdIn:18.35 Warning: calling polyEqual
Run Code Online (Sandbox Code Playgroud)
为什么我在下面的陈述中有"a而不是a":
val alreadyVisited = fn : ''a * ''a list -> bool
Run Code Online (Sandbox Code Playgroud)
这是功能:
fun alreadyVisited(v, []) = false
| alreadyVisited(v, x::xs) = if(x=v) then true
else alreadyVisited(v, xs);
Run Code Online (Sandbox Code Playgroud)
提前致谢
我的程序(Hartree-Fock /迭代SCF)有两个矩阵F和F',它们实际上是用两个不同的基数表示的相同矩阵.我只是失去了三个小时的调试时间,因为我不小心使用F'代替F.在C++中,类型检查器没有捕获这种错误,因为两个变量都是Eigen::Matrix<double, 2, 2>
对象.
我想知道,对于Haskell/ML /等.人们,无论你是否正在编写这个程序,你都会构建一个F和F'有不同类型的类型系统?那会是什么样的?我基本上试图了解如何将一些逻辑错误外包给类型检查器.
编辑:矩阵的基础就像单位.你可以说1L或多加仑,它们都意味着同样的事情.或者,为了给出一个矢量示例,可以在笛卡尔坐标中说(0,1)或在极坐标中说(1,pi/2).但即使含义相同,数值也不同.
编辑:也许单位是错误的比喻.我不是在寻找某种记录类型,我可以指定第一个字段是升和第二个加仑,而是说这个矩阵作为一个整体,用一些其他矩阵来定义(基础),其中基础可以是任何相同维度的矩阵.例如,构造函数看起来像是mkMatrix [[1, 2], [3, 4]] [[5, 6], [7, 8]]
,然后将该对象添加到另一个矩阵只有当两个对象具有与其第二个参数相同的矩阵时才进行类型检查.那有意义吗?