Для этого вам необходимо использовать API GHC - который включен в пакет ghc (который скрыт) - и плохо документирован.
Прилагаю здесь простую программу, которая распечатает список элементов верхнего уровня, экспортированных в модуль. Это должно послужить отправной точкой. Это небольшая утилита командной строки, которая принимает два аргумента - имя модуля и слово «класс», «данные», «функция». Так, например:
test Prelude function
напечатает список функций, экспортируемых модулем (те, которые не являются конструкторами или определить в классе).
Для того, чтобы скомпилировать это (при условии, что в test.hs
) вам нужно будет сделать:
ghc -package ghc test
для того, чтобы пакеты GHC API доступны.
Вот код:
import Data.List ((\\))
import Data.Maybe (fromJust, catMaybes)
import System.Environment (getArgs)
-- the GHC API stuff
import GHC
import GHC.Paths (libdir)
import ConLike (ConLike(..))
import Outputable (showPpr, showSDocUnqual)
import Var (tyVarName)
showU dfs = showSDocUnqual dfs . pprParenSymName
main = do
(mn : ty : _) <- getArgs
a <- runGhc (Just libdir) $ do
dflags <- getSessionDynFlags
setSessionDynFlags dflags
mm <- lookupModule (mkModuleName mn) Nothing
mi <- fmap fromJust $ getModuleInfo mm
res <- fmap catMaybes $ mapM lookupName (modInfoExports mi)
return $ case ty of
"class" -> [showU dflags c' | [email protected](ATyCon c') <- res, isClassTyCon c']
"data" -> [showU dflags c' | [email protected](ATyCon c') <- res, (not . isClassTyCon) c']
"function" -> let cf = map getName $ concat [(classMethods . fromJust . tyConClass_maybe) c' | [email protected](ATyCon c') <- res, isClassTyCon c']
df = map getName $ concat [ tyConDataCons c' | [email protected](ATyCon c') <- res, (not . isClassTyCon) c']
ff = [ getName c | [email protected](AnId{}) <- res] \\ cf
fd = [ getName c | [email protected](AConLike (RealDataCon{})) <- res] \\ df
in [showU dflags x | x <- ff ++ fd]
_ -> ["need to specify: class, data, or function"]
print a
Список классов и определенных данных довольно проста. Список определенных функций включает функции, определенные в классах и конструкторах. Вышеприведенный код для функций исключает их (с \\ cf
и \\ df
).
a
- это сгенерированный список имен функций (или классов или данных).
Код, который будет ссылаться на эти функции, будет предметом другого вопроса (и ответа).
lookupModule
- это функция, которая загружает модуль для анализа.
Сочетание getModuleInfo
и modInfoExports
получает список «материала», который включает в себя список функций, экспортируемых из модуля.
Остальная часть кода касается получения этих имен в пригодной для использования форме.
Существует: Это называется Template Haskell. Это не так просто.Несколько поисков Google должны позволять вам отслеживать, какая небольшая документация существует для него. – MathematicalOrchid
Есть ли причина, по которой вы не можете выполнить 'migrationsToDo = [migration_2015_01_02, ...]', а затем просто 'map doMigrations migrationsToDo'? Вам не нужна какая-либо интроспекция; похоже, вы ничего не делаете с именами, просто вызываете функции. – user2407038
И добавление их в таблицу уже запущенных миграций. – Ralph