Как динамически вызывать функцию, которая определена в нескольких модулях в одной и той же сигнатуре - PullRequest
5 голосов
/ 05 сентября 2011

Я определил много функций (скажем, 100+), каждая из которых выполняет определенную работу, но с одинаковой сигнатурой.Это что-то вроде:

module R001 (run) where run = <do-...>
module R002 (run) where run = <do-...>

То, что я хочу сделать, это обеспечить фактический «запуск» в качестве пользовательского ввода, например:

main = do
         runWith $ read $ getLine
       where
         runWith :: Int -> IO ()
         runWith n = R<n-padded-with-0>.run

В настоящее время я импортирую все модули, квалифицированные,и поместите все run в список [Maybe (IO())], так что это работает:

runWith n = case Rs !! (read $ getLine) of 
              Just run -> run
              Nothing -> undefined

Но по мере роста n я должен постоянно поддерживать большой список.

Можно ли каким-либо образом определить большой список с помощью TemplateHaskell или просто загрузить соответствующий модуль по мере необходимости во время выполнения, не разбивая каждый модуль на разные общие библиотеки.


На основе epsilonhalbe . Ответ, я провел некоторое исследование:

import R1 (run1)
import R2 (run2)

test = $(functionExtractor "^run")

main :: IO ()
main = do
         putStrLn $ show $ length $ test
         run1 -- remove on second attempt
         run2 -- remove on second attempt

Этот блок кода печатает 2 по результатам run1 и run2.Если я удаляю последние две строки, он просто печатает 0. Кажется, что функции, импортированные, но на которые нет ссылок, не будут извлечены ...

Ответы [ 2 ]

5 голосов
/ 05 сентября 2011

Однажды у меня была похожая проблема модуль загрузки haskell в списке , может быть, это поможет.

Вы можете создать список функций с помощью regexp и выбрать функцию по userinput из этого списка.Я не знаю, нужно ли вам импортировать все квалифицированные «прогоны» вручную или если вы можете

import R*.hs (run)

, я бы лучше написал один файл с run1 = …, run2 = … и сгенерировал бы список всехзапускает и функцию выбора функции, которая берет функцию из списка функций с такой же сигнатурой типа.

{-# LANGUAGE TemplateHaskell #-}
import Language.Haskell.Extract
import myRunFunctions

main = do
     let listOfRuns = $(functionExtractor "^run")
     putStrLn "please choose a run"
     putStrLn $ show listOfRuns
     let run = runWith $ read $ getLine
     run
   where
     runWith n = listOfRuns !! n

Внимание: у меня есть not , запустите этот код, это всего лишь потокМысль, заложенная в синтаксисе haskell

Надеюсь, это полезно


После редактирования:
В моем примере я написал все run* в одном файле итам я сгенерировал список всех функций запуска, которые работали мгновенно - взгляните на мой проект нуклеотидов , особенно файлы Rules.hs и Nucleotide.hs.

Runs.hs

module Runs where
import Language.Haskell.Extract

listOfRuns = map snd $(functionExtractor "^run")

run1 = …
run2 = …

Main.hs

import Runs

main = do
     putStrLn "please choose a run"
     putStrLn $ show listOfRuns
     let run = runWith $ read $ getLine
     run
  where
    runWith n = listOfRuns !! n

рад помочь

1 голос
/ 06 сентября 2011

Абсолютно важно, чтобы разные функции run жили в разных модулях?Если вы можете поместить их все в один модуль, вы можете сделать run функцией Int (или Integer, если хотите).

module AllMyCircuits where
run 0 = {- do blah blah blah -}
run 1 = {- do blah blah blah -}
run 2 = {- do yikes -}

module Main where
import AllMyCircuits
main = readLn >>= run
...