Cómo llamar dinámicamente una función que se definió en múltiples módulos en la misma firma
-
25-10-2019 - |
Pregunta
He definido muchas funciones (digamos, más de 100), cada una de las cuales hace un trabajo específico pero con la misma firma. Eso es algo como:
module R001 (run) where run = <do-...>
module R002 (run) where run = <do-...>
Lo que quiero hacer es proporcionar la "ejecución" real como entrada del usuario, de modo que:
main = do
runWith $ read $ getLine
where
runWith :: Int -> IO ()
runWith n = R<n-padded-with-0>.run
Actualmente, importo todos los módulos calificados y pongo todos los run
está en una lista de [Maybe (IO())]
, entonces esto funciona:
runWith n = case Rs !! (read $ getLine) of
Just run -> run
Nothing -> undefined
Pero como el n
Crece, tengo que mantener continuamente una gran lista.
¿Hay alguna forma de definir la lista grande usando Templatehaskell, o simplemente cargar el módulo correspondiente según sea necesario en el tiempo de ejecución sin tener que separar cada módulo en diferentes bibliotecas compartidas?
Residencia en epsilonhalbeRespuesta, investigué un poco:
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
Este bloque de código imprime 2 siguiendo los resultados de run1
y run2
. Si elimino las dos últimas líneas, solo imprime 0. Parece que las funciones importadas pero no referenciadas no se extraerán ...
Solución
Una vez tuve un problema similar módulo de carga de Haskell en la lista Tal vez esto ayuda.
Puede crear una lista de funciones con REGEXP y elegir una función de UserInput de esa lista. No sé si tienes que importar todas las "ejecuciones" calificadas a mano o si puedes
import R*.hs (run)
Prefiero escribir un archivo con run1 = …
, run2 = …
y generar una lista de todas las ejecuciones y una función de selección de funciones que toma una función de una lista de funciones con el mismo tipo de firma.
{-# 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
Atención: tengo no Ejecute este código Esto es solo un flujo de pensamiento puesto en la sintaxis de Haskell
Espero que esto sea útil
Después de editar:
En mi ejemplo escribí todo run*
En un archivo y allí generé la lista de todas las funciones de ejecución, que funcionaron instantáneamente, eche un vistazo a mi Proyecto de nucleótidos especialmente los archivos Rules.hs
y 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
Feliz de ser útil
Otros consejos
¿Es absolutamente crítico que los diferentes run
¿Las funciones viven en diferentes módulos? Si puedes ponerlos todos en un módulo, puedes hacer run
ser una función de un Int
(o Integer
si tu prefieres).
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