Динамический импорт
Если вы можете перечислить все возможные типы для функций C, которые могут быть вызваны, то вы можете использовать возможность динамического импорта FFI (http://www.haskell.org/onlinereport/haskell2010/haskellch8.html).. Функция динамического импорта оборачивает функцию C во время выполнения. Вам потребуется объявить функцию импорта для каждого типа функции C, который вы можете вызывать. (На самом деле, имеет значение только ABI, поэтому вы можете рассматривать все типы указателей C как эквивалентные.)
foreign import ccall "dynamic" mkPtrFun :: FunPtr (Ptr () -> IO (Ptr ())) -> Ptr () -> IO (Ptr ())
Если у вас есть указатель на функцию C, вы можете сделать ее вызываемой из Haskell, используя эту функцию-обертку.
callWithNull :: FunPtr (Ptr a -> IO (Ptr ())) -> IO (Ptr ())
callWithNull f = mkPtrFun f nullPtr
Если типы функций C неизвестны при компиляции кода на Haskell, вы не можете сделать это с помощью FFI.
Динамическая загрузка
Что касается динамического получения указателей на функции C, FFI вам не поможет. Вы можете использовать библиотеки динамической загрузки в C, такие как libdl. Смотрите справочные страницы: http://linux.die.net/man/3/dlopen.