Возможно, FFI позволяет экспортировать функции высшего порядка. Однако необходимо внести некоторые изменения в ваш Haskell:
{-# LANGUAGE ForeignFunctionInterface #-}
module Main where
import Foreign.C.Types
import Foreign
foreign export ccall sample_hs :: CInt -> IO (FunPtr Sample)
type Sample = CInt -> CInt
foreign import ccall "wrapper" mkSample :: Sample -> IO (FunPtr Sample)
sample_hs :: CInt -> IO (FunPtr Sample)
sample_hs x = mkSample (x+)
main = return ()
Функции высшего порядка экспортируются в Haskell с использованием явного типа FunPtr . Просто чтобы прояснить ситуацию, в данном случае я назвал более упорядоченный тип Sample . Чтобы создать указатель на функцию, вам нужно использовать функцию-обертку, отсюда и дополнительное объявление FFI.
Я не проверял это, но оно должно работать нормально, оно все равно компилируется. Подробнее о FunPtr здесь
- РЕДАКТИРОВАТЬ Я проверил его, и он отлично работает. возвращает 5, как и ожидалось.
Если вы случайно сделаете это для Windows, у меня есть пакет для взлома Hs2Lib , который экспортирует функции Haskell и автоматически компилирует их в .DLL. Он также предоставляет вам включает в себя для C / C ++ и C #. Однако, если вы работаете в Linux, я все еще работаю над этим.
бесстыдная вилка: P
При использовании Hs2Lib единственное, что вам нужно в вашем файле:
module Test where
-- @@ Export
sample_hs :: Int -> IO (Int -> Int)
sample_hs x = return (x+)
и простой вызов Hs2lib
PS C:\Users\Phyx\Desktop> hs2lib .\Test.hs
Linking main.exe ...
Done.
Причина ввода-вывода и явного возврата заключается в том, что Int -> (Int -> Int) - это просто Int -> Int -> Int, поскольку типы ассоциативно справа. Но Int -> IO (Int -> Int) указывает, что вы хотите вернуть функцию. Это в IO, потому что создание указателя на функцию - побочная операция.
Для полноты использовался файл C:
#include <stdio.h>
#include <stdlib.h>
#include "Hs2lib_FFI.h"
/*
*
*/
int main(int argc, char** argv) {
HsStart();
CBF1_t pf = sample_hs(2);
int result = pf(3);
printf("%d\n", result);
HsEnd();
return (EXIT_SUCCESS);
}
Так что это довольно плагин. Но опять же, сейчас это работает только для Windows.