So rufen Sie dynamisch eine Funktion auf, die in mehreren Modulen in derselben Signatur definiert wurde
-
25-10-2019 - |
Frage
Ich habe viele Funktionen definiert (z. B. 100+), von denen jede eine bestimmte Arbeit ausführt, aber mit der gleichen Signatur. Das ist so etwas wie:
module R001 (run) where run = <do-...>
module R002 (run) where run = <do-...>
Ich möchte den tatsächlichen "Auslauf" als Benutzereingabe bereitstellen, damit:
main = do
runWith $ read $ getLine
where
runWith :: Int -> IO ()
runWith n = R<n-padded-with-0>.run
Derzeit importiere ich alle qualifizierten Module und setze alle ein run
's in eine Liste von [Maybe (IO())]
, also funktioniert das:
runWith n = case Rs !! (read $ getLine) of
Just run -> run
Nothing -> undefined
Aber wie das n
Wächst, ich muss eine große Liste kontinuierlich unterhalten.
Gibt es eine Möglichkeit, die große Liste mit TemplateHaskell zu definieren oder das entsprechende Modul nach Bedarf zur Laufzeit zu laden, ohne jedes Modul in verschiedene freigegebene Bibliotheken zu trennen zu müssen?
Bezogen auf EpsilonhalbeAntwort, ich habe einige Nachforschungen angestellt:
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
Dieser Codeblock druckt 2 nach den Ergebnissen von run1
und run2
. Wenn ich die letzten beiden Zeilen entferne, druckt es nur 0. Es scheint, dass die importierten Funktionen, aber nicht verwiesen werden, nicht extrahiert werden ...
Lösung
Ich hatte einmal ein ähnliches Problem Haskell -Lastmodul in der Liste vielleicht hilft das.
Sie können eine Liste von Funktionen mit regexp erstellen und eine Funktion von UserInput aus dieser Liste auswählen. Ich weiß nicht, ob Sie alle von Hand qualifizierten "Läufe" importieren müssen oder ob Sie können
import R*.hs (run)
Ich würde lieber eine Datei schreiben run1 = …
, run2 = …
und generieren Sie eine Liste aller Läufe und eine Funktionswählerfunktion, die eine Funktion aus einer Liste von Funktionen mit derselben Typ -Signatur entnimmt.
{-# 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
Achtung: Ich habe nicht Führen Sie diesen Code aus. Dies ist nur ein Strom von Gedanken, die in die Haskell -Syntax eingestuft werden
Ich hoffe das ist hilfreich
Nach der Bearbeitung:
In meinem Beispiel habe ich alle geschrieben run*
In einer Datei und dort habe ich die Liste aller ausgeführten Funktionen generiert, die sofort funktionierten - schauen Sie sich meine an Nukleotidprojekt vor allem die Dateien Rules.hs
und 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
glücklich, hilfsbereit zu sein
Andere Tipps
Ist es absolut kritisch, dass die unterschiedlich run
Funktionen leben in verschiedenen Modulen? Wenn Sie sie alle in ein Modul legen können, können Sie es machen run
eine Funktion von einem sein Int
(oder Integer
Wenn Sie es vorziehen).
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