Оценка операторов / выражений на языке Haskell с использованием GHC API
Для инструмента, который я пишу ( http://hackage.haskell.org/package/explore), мне нужен способ чтения определений функций haskell во время выполнения, применения их к значениям из моего инструмента и получения результатов их применения.,
Кто-нибудь может дать мне очень простой пример использования API GHC (6.10.4 или 6.12.1)?
пример определения функции для чтения из файла во время выполнения:
f x = 10**(4/1102*x - 1)
ожидаемый результат программы
--mapM_ print $ map f [428, 410, 389]
3.577165388142748
3.077536885227335
2.5821307011665815
!!ОБНОВИТЬ!!
Я разместил быстрый ответ, но он создает объектный файл в каталоге выполнения, любые советы, чтобы этого избежать и избежать всех файловых операций ввода-вывода, приветствуются. Я также хочу увидеть версию, которая делает все в памяти: пользователь предоставляет определение функции в графическом интерфейсе, например, а компиляция / оценка не создает никаких объектных файлов.
3 ответа
Используйте подсказку. Это GHCi-подобная оболочка для GHC API, которая не очень сложна в использовании.
Если вы хотите пример его использования, я использовал его в своем проекте Йогурт.
Адаптировано из: http://www.bluishcoder.co.nz/2008/11/dynamic-compilation-and-loading-of.html
f.hs:
module Func (Func.f) where
f :: Double -> Double
f x = 10**(4/1102*x - 1)
main.hs:
import GHC
import GHC.Paths
import DynFlags
import Unsafe.Coerce
import Control.Monad
main :: IO ()
main =
defaultErrorHandler defaultDynFlags $ do
func <- runGhc (Just libdir) $ do
dflags <- getSessionDynFlags
setSessionDynFlags dflags
target <- guessTarget "f.hs" Nothing
addTarget target
r <- load LoadAllTargets
case r of
Failed -> error "Compilation failed"
Succeeded -> do
m <- findModule (mkModuleName "Func") Nothing
setContext [] [m]
value <- compileExpr ("Func.f")
do let value' = (unsafeCoerce value) :: Double -> Double
return value'
let f = func
mapM_ print $ map f [428, 410, 389]
return ()
Хорошая работа по запуску API. Я могу немного рассказать вам о том, как работает генератор кода.
GHC использует системный ассемблер для создания.o файла. Если нет возможности, чтобы GHC мог выполнить очистку после себя, то вам следует подать запрос функции к API, используя трекер ошибок по адресу http://hackage.haskell.org/trac/ghc/newticket?type=feature+request. Для того, чтобы подать запрос, вам необходимо зарегистрировать аккаунт.
Используя стандартный генератор кода, вы не сможете полностью избежать файлового ввода-вывода только потому, что GHC делегирует ассемблеру работу по созданию перемещаемого объектного кода. Существует экспериментальный бэкэнд, основанный на LLVM, который мог бы делать все в памяти, но я был бы удивлен, если бы он был доступен в чем-то более раннем, чем 6.13. Однако, возможно, стоит спросить в списке разработчиков GHC.