So rufen Sie dynamisch eine Funktion auf, die in mehreren Modulen in derselben Signatur definiert wurde

StackOverflow https://stackoverflow.com/questions/7306578

  •  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 ...

War es hilfreich?

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
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top