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

Оценка утверждений/выражений Haskell с использованием API GHC

Для инструмента, который я пишу (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

!! ОБНОВЛЕНИЕ!!

Я отправил быстрый ответ, но он создает объектный файл в каталоге выполнения, любые советы, чтобы избежать этого, и избегать всех файлов IO. Я хочу также увидеть версию, которая делает все в памяти: пользователь предоставляет определение функции в графическом интерфейсе, например, и компиляция/оценка не создает никаких объектных файлов.

4b9b3361

Ответ 2

адаптирован из: 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 ()

Ответ 3

Хорошая работа по запуску API. Я могу рассказать вам немного о том, как работает генератор кода.

GHC использует системный ассемблер для создания файла .o. Если нет возможности получить GHC для очистки после себя, тогда вы должны подать запрос функции на API, используя трекер ошибок в http://hackage.haskell.org/trac/ghc/newticket?type=feature+request. Чтобы подать запрос, вам необходимо зарегистрировать учетную запись.

Используя стандартный генератор кода, вы не сможете полностью избежать ввода-вывода файлов, просто потому, что GHC делегирует работу по созданию перемещаемого объектного кода на ассемблер. Существует экспериментальный задний конец, основанный на LLVM, который мог бы делать все в памяти, но я был бы удивлен, если он доступен в чем-либо раньше, чем 6.13. Однако, возможно, стоит обратиться к списку разработчиков GHC.