Cómo llamar dinámicamente una función que se definió en múltiples módulos en la misma firma

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

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

¿Fue útil?

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
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top