Подтвердить что ты не робот

Вызов функций Haskell из Python

Я хочу использовать некоторые библиотеки Haskell (например, Darcs, Pandoc) из Python, но, похоже, для Haskell в Python нет прямого интерфейса с иностранными функциями. Есть ли способ сделать это?

4b9b3361

Ответ 1

Если вы можете получить код Python для вызова C, вы можете вызвать функции Haskell, которые были экспортированы через FFI

Другим подходом было бы написать стандартный интерфейс IPC, в случае с darcs и pandoc, просто называя их исполняемыми файлами vanilla и анализируя их вывод, может быть, путь.

Что касается автоматизации генерации скучного, повторяющегося, FFI и кода маршаллинга на стороне Haskell, я бы рекомендовал c2hs, который позволяет автоматически генерировать множество на основе существующего интерфейса C. Вероятно, похожие вещи для python.

SWIG, увы, насколько мне известно, никогда не был реализован для Haskell, по-видимому, потому, что он обслуживает менее строго типизированные языки.

Ответ 2

Еще одна идея: что-то менее эффективное, чем прямое связывание C, но более эффективное, чем обход Haskell, представляет собой систему rpc, такую ​​как Apache Thrift: http://incubator.apache.org/thrift/

Я нашел, что бережливость проста в использовании, хорошо поддерживается и достаточно эффективна. После того, как у вас запущен сервер Haskell, стоимость локального общения довольно дешевая, хотя вы платите немного больше за маршаллинг /unmarshalling, чем напрямую с использованием типов c.

Есть также как минимум два пакета для вызова Python из Haskell, missingpy (http://hackage.haskell.org/package/MissingPy) и cpython (http://hackage.haskell.org/package/cpython). Последний утверждает, что поддержка в другом направлении запланирована - хотя вы должны спросить автора, если это все еще так, и если да, то когда.

Ответ 3

Существует оболочка, которая позволяет называть функции Haskell из Python здесь:

https://github.com/sakana/HaPy

От беглого осмотра, кажется, требуется, чтобы функции Haskell имели относительно простые сигнатуры типа (в основном, все типы были лучше, например, такие, как 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

Другой вариант - дефис, который можно найти здесь. Основное использование выглядит примерно так:

>>> 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. В то время как HaPy и github.com/nh2/call-haskell-from-anything позволяют использовать функцию Haskell с Python, если эта функция Haskell имеет все свои аргументы из довольно простых типов и возвращает довольно простой тип, hyphen, похоже, позволяет использовать произвольные функции. Он может это сделать, потому что он вводит в python тип, представляющий произвольный объект в куче Haskell.

Эти объекты haskell, просматриваемые с python, ведут себя довольно хорошо, как объекты 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]

См. readme для многих других примеров!

Он также обрабатывает различные причудливые вещи, такие как преобразование исключений между Haskell и Python.

Ответ 6

Noob здесь.

Но мне удалось вызвать пользовательские функции Haskell из python с использованием Haskell FFI. В основном я скомпилировал функцию Haskell в dll и импортировал dll с помощью ctypes в python. Таким образом, функция стала доступна в python.

Я написал процедуру здесь: https://justa0xc0de.wordpress.com/2015/01/08/using_haskell_function_in_python/

Надеюсь, что это поможет.