Es posible, FFI permite la exportación de funciones de orden superior. Algunas modificaciones a su Haskell se requiere sin embargo:
{-# 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()
funciones de orden superior se exportan en Haskell utilizando el tipo explícita FunPtr. Para aclarar un poco, he nombrado el tipo ordenado más alto Sample en este caso. Para poder crear un puntero de función, necesita usar una función de "envoltura", de ahí la declaración adicional de FFI.
No he probado esto, pero debería funcionar bien, compila de todos modos. Más sobre FunPtr here
- EDIT Lo he probado y funciona bien. devuelve 5 como se esperaba.
Si por casualidad lo haces en Windows, tengo un paquete en hackage Hs2Lib que exportaría las funciones de Haskell y las compilaría a un .DLL automáticamente. También le proporciona incluye para C/C++ y C#. Sin embargo, si estás en Linux, aún estoy trabajando en eso.
enchufe descarado: P
Usando Hs2Lib la única cosa que hay en su archivo es:
module Test where
-- @@ Export
sample_hs :: Int -> IO (Int -> Int)
sample_hs x = return (x+)
y una simple llamada a Hs2lib
PS C:\Users\Phyx\Desktop> hs2lib .\Test.hs
Linking main.exe ...
Done.
La razón de la IO y el retorno explícito es que Int -> (Int -> Int) es solo Int -> Int -> Int, ya que los tipos son correctos asociativos. Pero Int -> IO (Int -> Int) indica que desea devolver una función.Está en IO porque crear un puntero de función es una operación de efecto secundario. Para completar el archivo de C utilizado es:
#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);
}
así que es bastante plug-n-play. Pero, de nuevo, solo funciona para Windows por ahora.
La firma de funciones con la que estaba trabajando era mucho más compleja que el ejemplo, siguió su ejemplo y funcionó perfectamente, ¡gracias! –