Оценка операторов / выражений на языке Haskell с использованием GHC API - PullRequest
19 голосов
/ 16 марта 2010

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

6 голосов
/ 17 марта 2010

Использовать подсказка . Это GHCi-подобная оболочка для GHC API, которая не очень сложна в использовании.

Если вы хотите пример его использования, я использовал его в моем проекте Йогурт .

5 голосов
/ 16 марта 2010

адаптировано из: 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 ()
4 голосов
/ 16 марта 2010

Отличная работа по запуску API. Я могу немного рассказать вам о том, как работает генератор кода.

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

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

...