简体   繁体   English

从Python调用Haskell函数

[英]Calling Haskell functions from Python

I want to use some Haskell libraries (eg Darcs, Pandoc) from Python, but it seems there's no direct foreign function interface to Haskell in Python. 我想使用Python的某些Haskell库(例如Darcs,Pandoc),但似乎没有直接的外部函数接口可以在Python中使用Haskell。 Is there any way to do that? 有什么办法吗?

Provided you can get your Python code to call C, you can call Haskell functions that have been exported via the FFI 只要您可以获取Python代码来调用C,就可以调用已通过FFI导出的Haskell函数

Another approach would be to write a standard IPC interface, in the case of darcs and pandoc just calling them as vanilla executables and parsing their output might be the way to go. 另一种方法是编写一个标准IPC接口,在darcs和pandoc的情况下,仅将它们称为原始可执行文件并解析其输出可能是可行的方法。

As to automating the generation of boring, repetitive, FFI and marshalling code on the Haskell side, I'd recommend c2hs , which allows you to auto-generate a lot based on an existing C interface. 至于在Haskell方面自动生成无聊的,重复的,FFI和编组代码,我建议使用c2hs ,它使您可以基于现有的C接口自动生成大量代码。 There's probably similar things for python. python可能有类似的东西。

SWIG, alas, has, to the best of my knowledge, never been implemented for Haskell, presumably because it caters to less strictly-typed languages. 据我所知,SWIG从未为Haskell实施,大概是因为它可以迎合不太严格类型的语言。

One additional idea: Something less efficient than a direct C binding, but more efficient than shelling out to Haskell is an rpc system such as Apache Thrift: http://incubator.apache.org/thrift/ 一个另外的想法:诸如Apache Thrift之类的rpc系统要比直接C绑定的效率低,但比炮轰Haskell的效率更高: http : //incubator.apache.org/thrift/

I've found thrift easy to use, well supported, and reasonably performant. 我发现节俭易于使用,得到了良好的支持并且性能合理。 Once you have your Haskell server running, the cost of local communication is fairly cheap, although you pay a bit more in marshalling/unmarshalling than using c types directly. 运行Haskell服务器后,本地通讯的成本相当便宜,尽管在编组/解组方面要比直接使用c类型花费更多。

There are also at least two packages for calling Python from Haskell, missingpy ( http://hackage.haskell.org/package/MissingPy ) and cpython ( http://hackage.haskell.org/package/cpython ). 还有至少两个用于从Haskell调用Python的程序包:missingpy( http://hackage.haskell.org/package/MissingPy )和cpython( http://hackage.haskell.org/package/cpython )。 The latter claims that support in the other direction is planned -- although you'd have to ask the author if this is still the case, and if so when. 后者声称计划在另一个方向提供支持-尽管您必须问作者是否仍然如此,以及何时这样做。

Another option is hyphen , which can be found here . 另一种选择是连字符 ,可以在此处找到。 Basic usage looks something like: 基本用法如下所示:

>>> 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]

This seems to be a less lightweight solution than some of the other options in other answers. 与其他答案中的某些其他选项相比,这似乎是一种轻量级的解决方案。

In return for the extra weight, you seem to get a full bridge from Haskell to Python. 作为额外的回报,您似乎从Haskell到Python有了一个完整的桥梁。 Whereas HaPy and github.com/nh2/call-haskell-from-anything only allow you to use a Haskell function from Python if that Haskell function has all its arguments from fairly basic types and returns a fairly basic type, hyphen seems to let you use arbitrary functions. HaPygithub.com/nh2/call-haskell-from-anything仅允许您使用Python中的Haskell函数, github.com/nh2/call-haskell-from-anything是该Haskell函数的所有参数均来自基本类型,但hyphen似乎可以让您使用任意函数。 It can do this because it introduces into python a type representing an arbitrary object on the Haskell heap. 之所以可以这样做,是因为它在python中引入了一种表示Haskell堆上任意对象的类型。

These 'haskell objects viewed from python' behave fairly nicely as python objects. 这些“从python查看的haskell对象”的行为与python对象相当好。 For example Haskell Map s behave a bit like dictionaries: 例如,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]

See the readme for many more examples! 有关更多示例,请参见自述文件!

It also seems to handle various fancy things like converting exceptions between Haskell and Python. 它似乎也可以处理各种奇特的事情,例如在Haskell和Python之间转换异常。

Noob here. 菜鸟在这里。

But I did manage to call user defined Haskell functions from python using Haskell's FFI. 但是我确实设法使用Haskell的FFI从python调用了用户定义的Haskell函数。 Basically I compiled the Haskell function to a dll and imported the dll using ctypes in python. 基本上,我将Haskell函数编译为一个dll,并使用python中的ctypes导入了该dll。 So the function became available in python. 因此该功能在python中可用。

I wrote the procedure here: https://justa0xc0de.wordpress.com/2015/01/08/using_haskell_function_in_python/ 我在这里编写了过程: https//justa0xc0de.wordpress.com/2015/01/08/using_haskell_function_in_python/

Hope this helps. 希望这可以帮助。

There is a wrapper that allows one to call Haskell functions from Python here: 这里有一个包装器,允许用户从Python调用Haskell函数:

https://github.com/sakana/HaPy https://github.com/sakana/HaPy

From a cursory inspection, it seems to require that the Haskell functions have relatively simple type signatures (basically, all the types involved had better be things like Int and Float which c knows about, or lists of things of this form, or lists of lists, or so on). 从粗略的检查来看,似乎要求Haskell函数具有相对简单的类型签名(基本上,所涉及的所有类型最好是c知道的Int和Float之类的东西,或者这种形式的事物的列表,或者列表的列表) ,等等)。

An example is provided where one has this Haskell code: 提供了一个具有以下Haskell代码的示例:

module ExampleModule where

import Data.Char

foo :: Double -> Double -> Double
foo = (*)

bar :: Int -> Int
bar i = sum [1..i]

baz :: Int -> Bool
baz = (> 5)

arr_arg :: [Int] -> Int
arr_arg = sum

arr_ret :: Int -> [Int]
arr_ret i = [1..i]

arr_complex :: [[Int]] -> [[Int]]
arr_complex = map (map (* 2))

string_fun :: String -> String
string_fun str = str ++ reverse str

char_test :: Char -> Int
char_test = ord

and one accesses it like this: 一个这样访问它:

from HaPy import ExampleModule

print "3 * 7 is", ExampleModule.foo(3,7)
print "sum from 1 to 10 is", ExampleModule.bar(10)
print "3 > 5 is", ExampleModule.baz(3)

print "sum from 1 to 100 is", ExampleModule.arr_arg(range(101))
print "numbers from 1 to 10 are", ExampleModule.arr_ret(10)

print "complex array passing:", ExampleModule.arr_complex([range(3), [], range(100)])
print "string fun:", ExampleModule.string_fun("This isn't really a palindrome.")

s = ExampleModule.string_fun("abc\000def")
print "string fun with nulls:", s,
for c in s:
    print ord(c),
print

print "char test:", ExampleModule.char_test("t")

Unfortunately, you do need to do some export plumbing on the Haskell side. 不幸的是,您确实需要在Haskell端进行一些出口管道。

对于Pandoc,至少可以使用以下C绑定: https : //github.com/toyvo/libpandoc

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM