如何动态调用在同一签名中的多个模块中定义的函数

时间:2011-09-05 10:11:29

标签: haskell template-haskell

我已经定义了很多功能(例如,100 +),每个功能都执行特定的工作但具有相同的签名。这就像是:

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

我想做的是提供实际的'run'作为用户输入,例如:

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

目前,我导入了所有合格的模块,并将所有run放入[Maybe (IO())]的列表中,这样就可以了:

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

但随着n的增长,我必须不断维持一个大清单。

有没有办法可以使用TemplateHaskell定义大列表,或者只是在运行时根据需要加载相应的模块,而不必将每个模块分成不同的共享库。


基于 epsilonhalbe 的回答,我做了一些研究:

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

此代码块会在run1run2的结果后打印2。如果我删除最后两行,它只打印0.似乎导入但未引用的函数将不会被提取...

2 个答案:

答案 0 :(得分:5)

我曾遇到类似的问题haskell load module in list也许这会有所帮助。

您可以使用regexp创建函数列表,并通过userinput从该列表中选择一个函数。 我不知道你是否必须手动输入所有“跑步”,或者你可以

import R*.hs (run)

我宁愿用run1 = …run2 = …写一个文件并生成所有运行的列表和函数选择器函数,该函数从具有相同类型签名的函数列表中获取函数。

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

注意:我运行此代码这只是一个用haskell语法输入的思想流

我希望这很有用


修改后:
在我的例子中,我在一个文件中写了所有run*,然后我生成了所有运行函数的列表,这些函数立即生效 - 查看我的Nucleotide Project,特别是文件Rules.hs和{{ 1}}。

Nucleotide.hs

Runs.hs

module Runs where import Language.Haskell.Extract listOfRuns = map snd $(functionExtractor "^run") run1 = … run2 = …

Main.hs

乐意提供帮助

答案 1 :(得分:1)

不同的run函数是否存在于不同的模块中是绝对关键的吗?如果您可以将它们全部放在一个模块中,则可以runInt(或Integer的函数,如果您愿意的话)。

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