混合使用Haskell和C++

42
如果您有一个应用程序,可以同时使用Haskell和C++,您会让哪些层由Haskell管理,哪些层由C++管理?
是否已经有人做过这样的组合呢?
(Haskell网站称它非常容易,因为Haskell可以通过gcc编译为C)
首先,我认为我会将所有的I/O操作和GUI管理都保留在C++层。但是,随着我计划学习Haskell,我正在考虑将一些工作委派给Haskell代码,并选择一些部分来看到Haskell的好处。

描述您计划构建的应用程序类型将非常有用。 - Daniel
我有几个项目,每个都非常不同。重要的是了解Haskell比C++更擅长什么,然后尝试在其中的某些部分编写Haskell代码,以便学习Haskell并自行判断。 - Stephane Rolland
4个回答

28

Haskell的好处在于它允许您使用强大的抽象。您不再需要考虑二进制、地址和寄存器,而是可以考虑计算、类型属性和延续。

C++的好处在于必要时可以进行紧密的优化。您不再需要考虑高深的单子、箭头、部分应用和组合纯函数:使用C++,您可以直接到底层!

这两个观点之间存在一定的冲突。在他的论文“带有go to语句的结构化编程”中,Donald Knuth写道:

我很久以来一直感觉,编程才能主要包括随时转换微观和宏观视角的能力,即流畅地改变抽象层次。

了解如何使用Haskell和C++,以及在什么时候和如何将它们合理地结合起来,将有助于解决各种问题。

我最近写的一个大项目,涉及使用FFI,其中涉及使用C语言编写的公司内部雷达建模库。重新实现它是愚蠢的,而表达应用程序的高级逻辑则很痛苦。我在Haskell中保留了其“智力”,并在需要时调用了C库。

由于您希望将此作为练习进行,因此我建议采用相同的方法:在Haskell中编写应用的核心代码。如果将Haskell作为C++的从属语言,则可能会让您感到沮丧或浪费时间。在各自优势的地方使用每种语言。


1
谢谢你倒转我的立场。Haskell应该调用C++。我会尝试这个方法。但这也意味着应用程序的核心是由Haskell驱动的。所以你的意思是C++中可用的对象、函数和模板编程不如Haskel提供的灵活性?Haskel将紧密地遵循我可能构建的应用程序的基本流程和逻辑,这就是你的意思吗? - Stephane Rolland
3
感谢Knuth的文章(基础知识永远不会有害)。虽然它在ACM上不是免费可用的(我没有那里的账户),但可以在CiteSeerx下载。 - Stephane Rolland
@DeadMG,这就是我试图理解的。在什么程度上,他们觉得C++高级抽象可能与Haskell高级抽象相比不那么有竞争力。但是我读到的一些东西给了我一个线索:代码的简短性。据称,函数式代码可能会缩短2到10倍。使用Erlang语言甚至可以更多。 - Stephane Rolland
2
@Stephane 我们使用的语言会影响我们的思维方式。C++ 的命令式根源往往会使程序在表达“如何”方面变得复杂,而模式是编程语言中弱点的标志。向声明式方向发展,脚手架消失了,留下了本质,这样易于推理。当然,在 C++ 中编写优美的程序和在 Haskell 中编写丑陋的程序仍然是可能的,但学习多种范式将使您成为更好的程序员。 - Greg Bacon
2
@Stephane Rolland:如果你想学习Haskell,那就去学习Haskell,然后再回来问问题。"我怎样才能学好Haskell?"和"我怎样才能让Haskell和C++互操作?"是有区别的。@gbacon:我并不是想暗示你在抨击C++,只是我觉得你对它的高级功能给出了一个不公正的看法,我当然同意多范式更强大的观点。 - Puppy
显示剩余6条评论

11

以下是我的看法:

  • 函数式语言擅长转换数据。当你编写需要输入并对其进行映射/筛选/缩小的程序时,请使用函数式结构。Haskell 在 Web 应用中有很好的实际应用例子(基本上将存储在数据库中的数据转换为网页)。
  • 过程化语言(面向对象语言即为过程化语言)擅长处理副作用和对象之间的通信。它们笨拙地用于数据转换,但每当你想要做系统编程或与人类(任何类型的用户界面,包括客户端 Web 编程)进行(双向)交互时,它们能够清晰地完成任务。
  • 然而,一些人可能会认为用户界面应该具有功能性描述。我回答说,已经有很好的框架可以在 OOP 语言中轻松使用,因此应该采用这种方式。毕竟,以对象和对象之间的通信来思考 UI 组件是很自然的。
  • IO 只是工具:每当你将输入转换为输出时,Haskell(或其他 FP 语言)应该执行 IO。每当你与人类交流时,C++(或其他 OOP 语言)应该执行 IO。
  • 不必担心速度。当你对 Haskell 使用正确的工具时,它是高效的。当你对 C++ 或 Python 使用正确的工具时,它们也是高效的。

因此,假设我精通 Haskell、C、C++ 和 Python,下面是我的应用程序编写方式:

  • 如果我的应用程序的主要功能是转换数据,则我使用 Haskell 编写,可能还会使用一些低层部分的 C 代码(这些 C 代码可能再调用一些高级底层部分的 C++ 代码,但为了可移植性原因,我将采用 C 作为接口)。
  • 如果我的应用程序的主要功能是与用户交互,则我使用 Python(例如 PyQt),并让 Python 调用由 C++ 编写的性能关键例程(boost::python 是一个相当不错的绑定生成器)。我还可能需要调用一些转换或提取数据的子例程,这些例程将使用 Haskell 编写。
  • 如果我必须在 Haskell 中编写应用程序的一部分,则我将其隔离成一个可以由 C 调用的 API。
  • 有时候,一个从标准输入读取数据并将结果写回标准输出的Haskell应用程序,作为一个子模块是很有用的(您可以在平台上使用fork/exec等方式调用它)。有时候,一个shell脚本是这类应用程序的正确包装器。

  • 随着时间的推移,我已经开始使用F#而不是Haskell。主要是因为它更简单,并且与.Net兼容。当我熟悉了F#后,我会回到Haskell。我对函数式编程的看法也同样适用于Haskell和F#,期待听取您的意见。 - Stephane Rolland
    我还在思考你的帖子。当你提到函数式编程对于转换(例如Web应用程序)非常有好处:给定一个数据库和一个图形主题->网站。但是我还没有听说过Haskell网站编程,你能为我解释一下吗? - Stephane Rolland
    @Stephane:这主要是因为大多数Web程序员通常没有深入的计算机科学知识... Web编程主要依赖于php(这很糟糕)。你可以使用F#与ASP.Net(我怀疑这是引入F#的主要原因),这是好的。看看http://www.haskell.org/haskellwiki/Practical_web_programming_in_Haskell,体会在函数式语言中进行Web编程的美丽和简单。 - Alexandre C.

    7
    这篇答案更像是一个故事,而不是一个全面的答案,但在我的计算语言学论文中,我使用了Haskell、Python和C++的混合编程,还使用了一些我没有编写的C和Java工具。我发现将所有东西作为单独的进程运行最简单,使用Python作为粘合代码来启动Haskell、C++和Java程序。 C++是一个相当简单、紧凑的循环,用于计算特征出现次数。基本上它所做的就是数学和简单的I/O。我实际上通过让Python粘合代码编写一个充满#define的头文件并重新编译来控制选项。有点hacky,但它起作用了。 Haskell是所有中间处理的部分:从我使用的各种C和Java解析器的复杂输出中获取数据,过滤无关数据,并将其转换为C++代码所期望的简单格式。然后我将C++输出转换成LaTeX标记(以及其他格式)。 这是你会期望Python强大的领域,但我发现Haskell使得操作复杂结构更容易;Python可能更适合简单的行到行转换,但我在Python中编写代码时经常忘记输入和输出类型,因为我正在切割和切块解析树。 由于我经常像使用更结构化的脚本语言一样使用Haskell,所以我最终编写了一些文件I/O实用程序,但除此之外,内置的树和列表操作库就足够了。 总之,如果你有像我这样的问题,我建议使用C++来处理内存受限、速度关键的部分,使用Haskell进行高级转换,并使用Python来运行所有内容。

    2
    我的程序是批处理操作,没有GUI,因此C++和Haskell根本不会直接交流,只能通过文件进行通信。我使用Python的subprocess.Popen启动它们两个,以便最大化利用我的机器上的核心。因此,Python实际上也没有与其他语言进行交流。但是我发现我并不需要太多的C++,只需要中心的、最占用内存的算法即可。如果您需要大量使用C++,或者需要程序各部分之间密切合作,则我的方法可能效果不佳。 - Nathan Shively-Sanders
    “转换”是关键词。只有当您需要转换事物时,函数式语言才是正确的工具。 - Alexandre C.

    5
    我从未混合使用这两种语言,但是你的方法对我来说有点不太合适。Haskell更适合高级操作,而C++可以进行优化,并且对于紧密循环和其他性能关键代码最有益。
    Haskell最大的好处之一是将IO封装成monads。只要这个IO不是时间关键的,我认为没有理由在C++中这样做。
    对于GUI部分,你可能是正确的。 Haskell有大量的GUI库,但是C++有强大的工具,如QtCreator,可以大大简化繁琐的任务。

    不,这对你来说似乎并不颠倒。你明确地说:用Haskell做所有事情。除了GUI和时间关键操作之外。这就是你不理解我可能会混合两种语言的原因。有一个小原因让我留在C++岛上(尽管我还没有学好Haskell以进行任何比较),用C++仍然能感受到发生了什么,我指的是硬件操作。 - Stephane Rolland
    3
    我不认为pmr是这样说的。你问了相对优势是什么-而pmr的回答相当准确。如果你更喜欢用命令式的风格,那也可以。但这是你自己的感觉,不是你最初所问的语言擅长什么的比较。 - Yitz
    1
    是的,我完全同意这种感觉,尤其是因为我不太了解Haskell。(我做了pmr +1) - Stephane Rolland

    网页内容由stack overflow 提供, 点击上面的
    可以查看英文原文,
    原文链接