当前位置: 首页 > 知识库问答 >
问题:

为什么哈斯克尔(GHC)这么快?

赖浩荡
2023-03-14

Haskell(使用GHC编译器)比您预期的要快得多。如果使用得当,它可以接近低级语言。(Haskellers最喜欢做的一件事是尝试将C语言的5%以内(甚至超过它,但这意味着您使用的是一个低效的C程序,因为GHC将Haskell编译为C)。)我的问题是,为什么?

共有1个答案

涂选
2023-03-14

我同意Dietrich Epp的观点:这是GHC快速发展的几个因素的结合。

首先,也是最重要的,Haskell是非常高级的。这使编译器能够在不破坏代码的情况下执行积极的优化。

想想SQL。现在,当我编写select语句时,它可能看起来像一个命令式循环,但事实并非如此。它看起来像是在该表中的所有行上循环,试图找到与指定条件匹配的行,但实际上“编译器”(DB引擎)可能正在执行索引查找--这具有完全不同的性能特征。但是由于SQL是如此高级,“编译器”可以替代完全不同的算法,透明地应用多个处理器或I/O通道或整个服务器,等等。

您说“在运行时动态创建函数”听起来很慢,但如果仔细观察,实际上并没有这样做。可能看起来你有,但你没有。如果您说(+5),那么,这是硬编码到源代码中的。它不能在运行时更改。所以它不是真正的动态函数。即使是curried函数也只是将参数保存到数据块中。所有的可执行代码实际上都存在于编译时;没有运行时解释。(与其他一些具有“eval函数”的语言不同。)

想想帕斯卡。它很旧,没有人真正使用它了,但没有人会抱怨帕斯卡慢。它有很多不喜欢的地方,但慢并不是其中之一。Haskell并没有做很多与Pascal不同的事情,除了垃圾收集而不是手动内存管理。并且不可变数据允许对GC引擎进行几个优化[延迟计算会使其变得有些复杂]。

我想事情是Haskell看起来先进、复杂和高水平,每个人都认为“哦哇,这真的很强大,它一定是惊人的慢!”但事实并非如此。或者至少,这不是你所期望的方式。是的,它有一个惊人的打字系统。但你知道吗?这一切都发生在编译时。到运行时,它就消失了。是的,它允许您用一行代码构造复杂的ADT。但你知道吗?ADT只是结构的普通C联合。仅此而已。

是什么让哈斯克尔这么快?纯洁。静态类型。懒惰。但最重要的是,足够高级,编译器可以在不破坏代码预期的情况下从根本上改变实现。

但我想这只是我的看法...

 类似资料:
  • Scala开发人员学习IO单元体,因此一般的蹦床技术对于不可能进行尾调用优化的递归是必要的,我想知道Haskell是如何避免它的。 我知道Haskell是一种懒惰的语言,但是我想知道是否有人可以再详细说明一下。 例如,为什么ForeverM stackoverflow不在Scala中运行?好吧,我可以回答蹦床,我可以找到实际的代码,在图书馆和博客。我自己居然实现了一个基本的蹦床来学习。 在哈斯克尔

  • GHC能否简化id=(\(a,b)- 更复杂的情况呢: GHC将简化映射到映射中? 我试图使用简单的beta缩减,但由于糟糕的模式匹配,这些术语看起来是不可缩减的。 因此,我很好奇GHC的优化技术如何处理这个问题。

  • 我对Haskell比较陌生,我正在努力找到一种实现Haskell的span函数的方法。然而,我的问题比这更一般,因为我不知道如何使函数返回包含所需元素的列表或元组列表。我对列表的问题,例如: 是我不能让函数在列表列表中的第一个列表中添加一个元素。我只知道如何将另一个列表附加到列表列表中。 简而言之,如果您向我解释如何实现span函数,我希望这一切都会清楚。

  • :101:22:ERROR:•在表达式“count words”的第一个参数中的“hello”中,即表达式:countWords[“hello”,“hello”,“world”]中的“[”hello“,”hello“,”world“]”中,无法将预期类型“Char”与实际类型“[Char]”匹配• :101:31:error:•在表达式“count words”的第一个参数中的“world”中,即

  • 我正在尝试在 Haskell 中实现一个函数,该函数返回一个列表,其中包含玩家的所有可能动作。该函数的唯一参数是一个字符串,由棋盘的实际状态(在福赛斯-爱德华兹符号中)组成,后跟移动的玩家(b/w)。 符号示例:rnbqkbnr/pppppp/8/8/8/PPPPPPP/rnbqkbnr w(起始板状态) 移动以[origin]-[destination]格式的字符串传输。目的地始终是形式[col

  • 我正在为一个2人棋盘游戏编写一个基本的MiniMax算法。到目前为止,我有一个函数,它评估一个板并返回一个分数。我有一个函数,它将所有可能的移动(以及这些移动的移动)等的玫瑰树返回到给定的深度。我可以找到那棵树的叶子,并根据我的启发给它们一个值,我的问题是,在那之后我该怎么办? 我是否以某种方式编辑叶子的父节点,并根据子节点的值给父节点分配一个新值,然后继续下去,直到到达根节点? 我是否要从叶子向