How to dynamically call a function which defined in multiple modules in the same signature

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

  •  25-10-2019
  •  | 
  •  

Question

I've defined a lot of functions (say, 100+), each of which do a specific work but with the same signature. That is something like:

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

What I wanna do is to provide the actual 'run' as user input, such that:

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

Currently, I import all modules qualified, and put all the run's into a list of [Maybe (IO())], so this works:

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

But as the n grows, I have to continously maintain a big list.

Is there any way I can define the big list using TemplateHaskell, or just load the corresponding module as needed at runtime without having to seperate each module into different shared libraries.


Based on epsilonhalbe's answer, I did some research:

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

This block of code prints 2 following the results of run1 and run2. If I remove the last two lines, it just prints 0. It seems that functions imported but not referenced won't be extracted ...

Was it helpful?

Solution

I once had a similar problem haskell load module in list maybe this helps.

You can create a list of functions with regexp and choose a function by userinput from that list. I don't know if you have to import all "runs" qualified by hand or if you can

import R*.hs (run)

i would rather write one file with run1 = …, run2 = … and generate a list of all runs and a function chooser function which takes a function from a list of functions with the same type signature.

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

Attention: I have not run this code this is just a stream of thought put in haskell syntax

i hope this is helpful


After edit:
In my example i wrote all run* in one file and there i generated the list of all run functions, which worked instantly - have a look at my Nucleotide Project especially the files Rules.hs and 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

happy to be helpful

OTHER TIPS

Is it absolutely critical that the different run functions live in different modules? If you can put them all in one module, you could make run be a function of an Int (or Integer if you prefer).

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
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top