从Python调用Haskell函数

时间:2011-02-16 10:46:42

标签: python haskell binding ffi

我想使用Python中的一些Haskell库(例如Darcs,Pandoc),但似乎在Python中没有直接的Haskell外部函数接口。有没有办法做到这一点?

6 个答案:

答案 0 :(得分:17)

如果您可以使用Python代码调用C,则可以调用已通过FFI

导出的Haskell函数

另一种方法是编写一个标准的IPC接口,在darcs和pandoc的情况下只是将它们称为vanilla可执行文件,解析它们的输出可能就是这样。

至于在Haskell端自动生成无聊,重复,FFI和编组代码,我建议c2hs,它允许您基于现有的C接口自动生成很多。 python可能有类似的东西。

据我所知,SWIG,从来没有为Haskell实现,大概是因为它迎合了不那么严格类型的语言。

答案 1 :(得分:9)

一个额外的想法:比直接C绑定效率低一些,但比向Haskell外壳更有效的是一个rpc系统,如Apache Thrift:http://incubator.apache.org/thrift/

我发现节俭易于使用,支持良好且性能合理。一旦你的Haskell服务器运行,本地通信的成本相当便宜,虽然你在编组/解组中支付的费用比直接使用c类型多一点。

还有至少两个用于从Haskell调用Python的包,missingpy(http://hackage.haskell.org/package/MissingPy)和cpython(http://hackage.haskell.org/package/cpython)。后者声称计划在另一个方向提供支持 - 尽管你必须询问作者是否仍然如此,如果是这样的话。

答案 2 :(得分:7)

另一个选项是连字符,可以找到here。基本用法类似于:

>>> 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&#39;中查看这些&#39; 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之间转换异常。

答案 3 :(得分:5)

有一个包装器允许人们在这里从Python调用Haskell函数:

https://github.com/sakana/HaPy

从粗略的检查中,似乎要求Haskell函数具有相对简单的类型签名(基本上,所涉及的所有类型最好是像int知道的Int和Float,或者这种形式的事物列表,或者列表清单等等。

提供了一个示例,其中一个具有此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

一个人就这样访问:

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")

不幸的是,你确实需要在Haskell端做一些导出管道。

答案 4 :(得分:4)

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

答案 5 :(得分:3)

Noob在这里。

但我确实设法使用Haskell的FFI从python调用用户定义的Haskell函数。 基本上我将Haskell函数编译为dll并使用python中的ctypes导入dll。 所以函数在python中可用。

我在这里写了这个程序:https://justa0xc0de.wordpress.com/2015/01/08/using_haskell_function_in_python/

希望这有帮助。