Haskell的类型系统是理解函数式编程的障碍吗?[关闭]


33

我正在研究Haskell,目的是理解函数式编程,并期望我将应用在其他语言(主要是Groovy,Python,JavaScript)中获得的见解。

我之所以选择Haskell,是因为我有一个印象,那就是它纯粹是功能性的,不会允许任何对状态的依赖。

我没有选择学习Haskell,因为我对导航一个非常严格的类型系统感兴趣。

我的问题是:强类型系统是否是一种极其纯净的功能语言的必要副产品,还是这与Haskell无关的设计选择?


6
如果您不想显式键入任何内容,则不需要显式键入任何内容。Haskell可以自行推断类型。而且这不像您将要拥有一个可能存储两个不兼容类型的变量一样。
Anon。

4
@Anon是的,但您的列表必须相同。相信我,即使有类型推断,这种事情也会阻碍。
埃里克·威尔逊

13
@FarmBoy,使用Maybe有什么问题?Java确实使您可以在所有类上使用Maybe,这是很奇怪的事情。
替代

3
而且,如果您确实要使用异构列表,则可以使用代数数据类型。
替代

1
@mathepic至此,我们真的忘记了我原来的问题,那是一个完全有效的问题。
埃里克·威尔逊

Answers:


40

我相信理解Haskell的类型系统是理解函数编程的放大器。

关于纯函数式编程的问题是,在没有副作用的情况下,副作用使您可以隐式地做各种事情,纯函数式编程使程序的结构更加明确。

Haskell阻止您将东西扔在地毯下,强迫您显式地处理程序的结构,并且它教您一种描述这些结构的语言:类型语言。了解类型,尤其是Haskell这样的丰富类型,将使您成为使用任何语言的更好的程序员。

如果没有强类型化Haskell,那么诸如monads,应用函子等之类的概念将永远不会应用于编程。


2
这是一个很好的答案,我的补充是,虽然类型系统一开始可能看起来很不正常,但是后来当您开始学习更高级的概念时,您会发现有些事情只能由于遵守该类型而得以完成系统(将STM和Data Parallel添加到上面的列表中)。Haskell系统自然适合其他类型的系统。我的建议:坚持一段时间,让它逐渐沉入(这不是“补习”语言)。
匿名

2
我知道这是一个非常古老的答案,但我实际上不同意。我认为,作为明确的一些东西可能在语言,类型系统,尤其是与单子,如国家和秒差距,扫一TON的东西在地毯下。实际上,这极大地干扰了我学习语言库的能力。
Savanni D'Gerinel

4
@ SavanniD'Gerinel:我认为在这个答案中,“把东西扔在地毯下”并不意味着增加隐式功能(Haskell以受控方式(例如通过单子)进行操作,并有助于减少样板),而是允许一些代码做一些不希望做的事情。例如:Haskell中的纯函数永远不会有副作用。期。在许多其他语言中,您可以在函数的文档中保证这一点,但是用您的语言编写的任何内容都不会阻止您在代码中的某些地方产生一些副作用。
Giorgio 2014年

33

最动态类型化的功能语言可以说是Scheme。也就是说,Haskell的类型系统是其纯度的指标。这是“如何测量纯度?”的问题。Haskell的类型系统使您可以轻松地封锁中的不纯行为IO。为此,您需要一个静态类型系统。

但是,可以说Haskell的类型系统与函数式编程无关。声称类型系统对您的教育工作无济于事,这仍然是一种狂妄自大的感觉。Haskell的类型系统既丰富又复杂,与C ++和OCaml的类型系统相比,更加有趣。

有障碍吗?不,我认为这是一种资产。试着不加IO举例地考虑如何处理Haskell的懒惰。


8
习惯了+1 Haskell的文字系统即可成为您的朋友。
拉里·科尔曼

“为此,您需要一个静态类型系统”。真?
乔恩·哈罗普

1
“与C ++和OCaml的类型系统相比,更有趣”。您是否研究过OCaml的一流高阶模块以及结构化类型的推断对象系统和多态变体?
乔恩·哈罗普

2
@JonHarrop或效果系统或某种测量/评估纯度的方法。是的,这就是为什么将它们进行比较很有趣。不同的选择会导致不同的语言。
Logan Capaldo'2

20

Clojure是动态类型的,几乎与Haskell一样纯净,因此有一个很好的论点,即Haskell的类型系统更多是设计选择,而不是绝对要求。两者肯定都有长处,因此,如果您真的不喜欢Haskell的僵化性,那么您可能要考虑Clojure(但请参见下文)。

当我第一次开始使用Haskell时,我认为类型系统很烦人,但由于类型推断而只能容忍它。我很快发现,编译器抱怨了很多类型错误,即使编译器允许我做这些事情也不管用(例如,不小心使用map而不是concatMap)。然后,我发现通过类型检查的程序通常是正确的,或者至少接近正确。我什至有一个懒惰的阶段,在该阶段我通过更改函数类型并让编译器告诉我还需要更改的内容来进行重构。最终,我意识到Haskell的类型系统实际上非常具有表现力,因此开始围绕类型设计我的程序。那就是Haskell的圣杯。


需要注意的另一件事:我大约同时使用Scheme和Haskell学习了函数式编程(前者用于一堂课,后者用于娱乐)。我发现,使用Haskell的模式匹配比使用Scheme中的s和s 来理解递归容易得多,我想这也可以延续到Clojure。ifcond
迪洪·杰维斯

@Larry Coleman:+1精确描述了我自己在类型系统方面的经验:首先是C ++,然后是Ocaml,现在是我自己的语言Felix。是的,我仍然通过追踪编译器错误来进行重构。
Yttrill 2012年

8

Haskell的类型系统是其将效果与纯代码隔离的能力的关键。除非可以用另一种方式隔离效果或完全删除效果,否则,纯函数式编程需要强大的静态类型系统。

Haskell是具有强大的静态类型系统的语言的一个很好的例子。如果您想在计算机科学和编程语言设计方面进行广泛而全面的教育,Haskell作为您应该学习的语言之一将是一个绝佳的选择。

类型系统不应该成为一个巨大的障碍。即使是在使用动态语言的情况下,编程人员也倾向于遵循可以使用Haskell的类型系统进行编码的输入约定。Haskell还具有类型推断功能,与C ++和Java之类的语言相比,它可以减轻冗长性。当您收到错误消息时,编译器只会在编译时告诉您动态类型的语言在运行时会告诉您什么。

动态类型系统的对立面是静态类型系统,而不是强类型系统。强类型系统与弱类型系统相反。


1
例如,C是静态但弱类型的。您有类型,但是很容易完全颠覆类型系统,使用底层的机器特定表示法等。很容易对许多动态类型化的语言OTOH进行强类型化-隐式强制转换很少,颠覆类型系统的方法很少(如果有的话)。
Steve314 2011年

4

当您犯下愚蠢的错误时,它会立即告诉您。这是有帮助的。我上个学期一直在Racket(Scheme)工作,有很多次我通过了一个未解析的s-exp,我期望我的解释器中的某个函数解析为ast,并且它只出现在我的解释器中。中型测试套件。如果我有一些静态类型,那将立即引起我的注意。

当然,类型系统并不能真正捕获逻辑错误,但是大大减少了解决错误的方法。

同样,如果需要,使用类型推断可以忽略类型系统。它仍然存在,但是不需要您的有效输入。理解函数的类型仍然很有帮助,但是正确的代码可以正常工作。

Haskell的纯度在其类型系统中进行了编码。IO monad是一种类型级别的构造,可防止不纯的代码泄漏到纯函数中,因此类型系统可确保其纯度。


8
如果您认为可以忽略Haskell的类型系统,那么我认为您没有编写太多Haskell。
埃里克·威尔逊

不要忽略,而是忽略它,就像键入该函数一样,将其加载到GHCi中,然后对其进行:t操作。但是有时您仍然需要使用一些来自Integral或其他功能的东西。
Theo Belaire 2010年

1
即使有类型推断,Tyr仍然有90%的使用和编码Haskell函数使该死的东西相互啮合,这需要了解其类型系统和奥秘的类型检查错误消息。即使“:t”也不是一个神奇的解决方案,这只是了解如何使程序进行编译的第一步。
Andres F.

好吧,我同意某些部分是混乱的。我真的认为序幕中的数字内容可能会被清理和修复,因为就目前而言,这真是一团糟。但是大多数关键功能方面都很干净。map,filter,foldr / l和其他有趣的功能函数可以很好地工作。
Theo Belaire

2

作为一种“功能”语言,(除其他因素外)意味着功能是该语言中的一流对象。

作为一种“纯”语言,意味着函数是数学函数(与过程相对)-给定相同的输入,它们始终会产生相同的输出。

“纯功能性语言”是以上两种情况都适用的一种语言。我不知道一个“纯铁的LY函数式语言”。

强类型系统是拥有纯净而实用的语言的一种干净方法。这些类型可以帮助编译器找出优化方案,并进一步确保正确性。(但是,这不是唯一的方法-clojure是纯净的,但没有Haskell那样强大的类型系统。)

如果类型系统困扰您,我建议您尝试使用更具动态性的语言(例如Scheme),或者着手使用Haskell的类型推断系统。


0

是的,类型系统是不可思议的资产。甚至很难描述单子的工作方式或某些没有类型系统的组合器的工作方式。考虑一下Haskell上有多少教程首先要求您考虑在REPL中带:t的函数的类型。对于动态类型的语言,这根本不可用。当然,类型系统的所有复杂性仍然存在。单子仍然是单子。但是语言已经决定要解决这个问题,根本不提供任何帮助。你一个人,朋友。我没有敲动态类型的语言。我深爱着他们。Scheme是出色的电动工具。但是您会注意到,当我们用动态语言谈论诸如monad之类的东西时,我们经常会发明一种符号描述程序的类型。函数式程序员将以一种或另一种方式与类型作斗争。Haskell的类型检查器只是为您提供了学习方法。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.