从Python调用Haskell函数

36 投票
6 回答
17492 浏览
提问于 2025-04-16 11:55

我想在Python中使用一些Haskell的库,比如Darcs和Pandoc,但好像Python没有直接和Haskell连接的接口。有没有什么办法可以做到这一点呢?

6 个回答

11

还有一个额外的想法:有一种比直接用C语言绑定效率低,但比调用Haskell更高效的方式,那就是使用像Apache Thrift这样的远程过程调用(rpc)系统:http://incubator.apache.org/thrift/

我发现Thrift使用起来很简单,支持也很好,性能也不错。一旦你的Haskell服务器启动了,本地通信的成本相对较低,虽然在数据转换上花费会比直接使用C语言的类型多一点。

另外,还有至少两个可以从Haskell调用Python的包,分别是missingpy(http://hackage.haskell.org/package/MissingPy)和cpython(http://hackage.haskell.org/package/cpython)。后者声称计划支持反向调用——不过你得问一下作者,这个计划是否还在进行,如果是的话,什么时候会实现。

12

另一个选择是 hyphen,你可以在 这里找到它。基本用法看起来像这样:

>>> import hyphen, hs.Prelude
>>> hs.Prelude.sum([1,2,3]) # list converted to Haskell list
6
>>> hs.Prelude.drop(5, "Hello, world")
", world"
>>> hs.Prelude.drop(1, [1,2,3])
<hs.GHC.Types.[] object of Haskell type [GHC.Integer.Integer], containing '[2,3]'>
>>> list(hs.Prelude.drop(1, [1,2,3]))   # Convert back to Python list
[2, 3]

这个方案似乎比其他一些答案中的选项要重一些。

不过,作为回报,你可以实现从 Haskell 到 Python 的完整桥接。相比之下,HaPygithub.com/nh2/call-haskell-from-anything 只允许你在 Python 中使用 Haskell 函数,前提是这个 Haskell 函数的所有参数都是比较简单的类型,并且返回的类型也比较简单,而 hyphen 似乎可以让你使用 任意 函数。它之所以能做到这一点,是因为它在 Python 中引入了一种表示 Haskell 堆上任意对象的类型。

这些“从 Python 看到的 Haskell 对象”在 Python 中表现得相当不错。例如,Haskell 的 Map 类似于字典:

>>> import hs.Data.Map
>>> my_map = hs.Data.Map.fromList([(1, 'Hello'), (2, 'World')])
>>> my_map[1]
'Hello'
>>> print(sorted([key for key in my_map]))
[1, 2]

想要更多示例,可以查看自述文件!

它似乎还可以处理一些复杂的事情,比如在 Haskell 和 Python 之间转换异常。

22

如果你能让你的Python代码调用C语言的代码,那么你就可以调用通过FFI导出的Haskell函数。

另一种方法是写一个标准的进程间通信接口。以darcs和pandoc为例,直接把它们当作普通的可执行文件来调用,并解析它们的输出,可能是个不错的选择。

至于在Haskell那边自动生成那些无聊、重复的FFI和数据转换代码,我推荐使用c2hs,它可以根据现有的C接口自动生成很多代码。对于Python,可能也有类似的工具。

可惜的是,SWIG据我所知从来没有被用于Haskell,可能是因为它主要针对那些类型不那么严格的语言。

撰写回答