我正在研究Haskell,目的是理解函数式编程,并期望我将应用在其他语言(主要是Groovy,Python,JavaScript)中获得的见解。
我之所以选择Haskell,是因为我有一个印象,那就是它纯粹是功能性的,不会允许任何对状态的依赖。
我没有选择学习Haskell,因为我对导航一个非常严格的类型系统感兴趣。
我的问题是:强类型系统是否是一种极其纯净的功能语言的必要副产品,还是这与Haskell无关的设计选择?
我正在研究Haskell,目的是理解函数式编程,并期望我将应用在其他语言(主要是Groovy,Python,JavaScript)中获得的见解。
我之所以选择Haskell,是因为我有一个印象,那就是它纯粹是功能性的,不会允许任何对状态的依赖。
我没有选择学习Haskell,因为我对导航一个非常严格的类型系统感兴趣。
我的问题是:强类型系统是否是一种极其纯净的功能语言的必要副产品,还是这与Haskell无关的设计选择?
Answers:
我相信理解Haskell的类型系统是理解函数编程的放大器。
关于纯函数式编程的问题是,在没有副作用的情况下,副作用使您可以隐式地做各种事情,纯函数式编程使程序的结构更加明确。
Haskell阻止您将东西扔在地毯下,强迫您显式地处理程序的结构,并且它教您一种描述这些结构的语言:类型语言。了解类型,尤其是Haskell这样的丰富类型,将使您成为使用任何语言的更好的程序员。
如果没有强类型化Haskell,那么诸如monads,应用函子等之类的概念将永远不会应用于编程。
最动态类型化的功能语言可以说是Scheme。也就是说,Haskell的类型系统是其纯度的指标。这是“如何测量纯度?”的问题。Haskell的类型系统使您可以轻松地封锁中的不纯行为IO
。为此,您需要一个静态类型系统。
但是,可以说Haskell的类型系统与函数式编程无关。声称类型系统对您的教育工作无济于事,这仍然是一种狂妄自大的感觉。Haskell的类型系统既丰富又复杂,与C ++和OCaml的类型系统相比,更加有趣。
有障碍吗?不,我认为这是一种资产。试着不加IO
举例地考虑如何处理Haskell的懒惰。
Clojure是动态类型的,几乎与Haskell一样纯净,因此有一个很好的论点,即Haskell的类型系统更多是设计选择,而不是绝对要求。两者肯定都有长处,因此,如果您真的不喜欢Haskell的僵化性,那么您可能要考虑Clojure(但请参见下文)。
当我第一次开始使用Haskell时,我认为类型系统很烦人,但由于类型推断而只能容忍它。我很快发现,编译器抱怨了很多类型错误,即使编译器允许我做这些事情也不管用(例如,不小心使用map而不是concatMap)。然后,我发现通过类型检查的程序通常是正确的,或者至少接近正确。我什至有一个懒惰的阶段,在该阶段我通过更改函数类型并让编译器告诉我还需要更改的内容来进行重构。最终,我意识到Haskell的类型系统实际上非常具有表现力,因此开始围绕类型设计我的程序。那就是Haskell的圣杯。
if
cond
Haskell的类型系统是其将效果与纯代码隔离的能力的关键。除非可以用另一种方式隔离效果或完全删除效果,否则,纯函数式编程需要强大的静态类型系统。
Haskell是具有强大的静态类型系统的语言的一个很好的例子。如果您想在计算机科学和编程语言设计方面进行广泛而全面的教育,Haskell作为您应该学习的语言之一将是一个绝佳的选择。
类型系统不应该成为一个巨大的障碍。即使是在使用动态语言的情况下,编程人员也倾向于遵循可以使用Haskell的类型系统进行编码的输入约定。Haskell还具有类型推断功能,与C ++和Java之类的语言相比,它可以减轻冗长性。当您收到错误消息时,编译器只会在编译时告诉您动态类型的语言在运行时会告诉您什么。
动态类型系统的对立面是静态类型系统,而不是强类型系统。强类型系统与弱类型系统相反。
当您犯下愚蠢的错误时,它会立即告诉您。这是有帮助的。我上个学期一直在Racket(Scheme)工作,有很多次我通过了一个未解析的s-exp,我期望我的解释器中的某个函数解析为ast,并且它只出现在我的解释器中。中型测试套件。如果我有一些静态类型,那将立即引起我的注意。
当然,类型系统并不能真正捕获逻辑错误,但是大大减少了解决错误的方法。
同样,如果需要,使用类型推断可以忽略类型系统。它仍然存在,但是不需要您的有效输入。理解函数的类型仍然很有帮助,但是正确的代码可以正常工作。
Haskell的纯度在其类型系统中进行了编码。IO monad是一种类型级别的构造,可防止不纯的代码泄漏到纯函数中,因此类型系统可确保其纯度。
是的,类型系统是不可思议的资产。甚至很难描述单子的工作方式或某些没有类型系统的组合器的工作方式。考虑一下Haskell上有多少教程首先要求您考虑在REPL中带:t的函数的类型。对于动态类型的语言,这根本不可用。当然,类型系统的所有复杂性仍然存在。单子仍然是单子。但是语言已经决定要解决这个问题,根本不提供任何帮助。你一个人,朋友。我没有敲动态类型的语言。我深爱着他们。Scheme是出色的电动工具。但是您会注意到,当我们用动态语言谈论诸如monad之类的东西时,我们经常会发明一种符号描述程序的类型。函数式程序员将以一种或另一种方式与类型作斗争。Haskell的类型检查器只是为您提供了学习方法。