2011-09-05 9 views
5

Mam zdefiniowane wiele funkcji (powiedzmy 100+), z których każda zrobić konkretną pracę, ale z tym samym podpisem. Że jest coś takiego jak:Jak dynamicznie wywołania funkcji, które zdefiniowano w wielu modułów w tym samym podpisem

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

Co chcę zrobić jest zapewnienie rzeczywistego „Uruchom” jako dane wejściowe użytkownika, takie, że:

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

Obecnie importować wszystkie moduły kwalifikacje i umieścić wszystkie run „s na listę [Maybe (IO())], więc to działa:

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

Ale jak n rośnie, muszę stale utrzymywać duże liście.

Czy jest jakiś sposób mogę zdefiniować dużą listę używając TemplateHaskell, lub po prostu załadować odpowiedni moduł, ile potrzeba na starcie, bez konieczności oddzielenia każdego modułu do różnych bibliotek współdzielonych.


podstawie epsilonhalbe „s odpowiedź, zrobiłem rozeznanie:

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 

ten blok drukuje kod 2 następującymi wynikami run1 i run2. Jeśli usunę ostatnie dwa wiersze, to po prostu wypisze 0. Wydaje się, że funkcje zaimportowane, ale nie wymienione, nie zostaną wyodrębnione ...

Odpowiedz

5

Miałem kiedyś podobny problem haskell load module in list może to pomaga.

Można utworzyć listę funkcji z regexp i wybrać funkcję przez userinput z tej listy. ja nie wiem, czy trzeba importować wszystko „działa” zakwalifikowane przez strony lub, jeśli można

import R*.hs (run) 

wolałbym napisać jeden plik z run1 = …, run2 = … i wygenerować listę wszystkich tras oraz funkcję Chooser funkcja, która przyjmuje funkcję z listy funkcji o tym samym podpisie typu.

{-# 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 

Uwaga: Mam nie uruchomić ten kod to tylko strumień myśli umieścić w składni Haskell

mam nadzieję, że jest to pomocne


Po EDIT:
W moim przykładzie napisałem wszystkie run* w jednym pliku i tam wygenerowałem listę wszystkich uruchomionych funkcji, które działały natychmiast - przyjrzyj się moim Nucleotide Project, szczególnie plikom Rules.hs i 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 

szczęśliwy być pomocne

+0

Dzięki! jest to bardzo pomocne, przynajmniej 'functionExtractor' jest dla mnie nowością. Zrobiłem trochę badań i zaktualizowałem pierwotny wpis. – claude

+0

To jest całkiem podobne do 'prop_ *' QuickChekc. Haskell Test Framework 'HTF', który zbiera wszystkie pakiety testowe HUnit/rekordy QuickCheck w jednym pliku, używa niestandardowego preprocesora' {- # OPTIONS_GHC -F -pgmF htfpp # -} '. To jest ostatnie rozwiązanie, którego chcę użyć, ale obawiam się, że to jedyne rozwiązanie? – claude

+0

Jestem zdecydowanie pewien, że nie jest to jedyne rozwiązanie - ale najlepsze, jakie mogę wymyślić. – epsilonhalbe

1

Czy jest absolutnie krytyczna, że ​​różne funkcje run żyć w różnych modułów? Jeśli umieścisz je wszystkie w jednym module, możesz ustawić run jako funkcję Int (lub (lub (lub jeśli wolisz).

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 
+0

dziękuję, to moje pierwsze rozwiązanie. Ale muszę je rozdzielić przynajmniej na małe jednostki kompilujące, aby zmiana na "run" nie spowodowała ponownej kompilacji innych. – claude

Powiązane problemy