Haskell modules are not even remotely first-class entities, as may be required, I'm afraid.
However, as bzn commented, Template Haskell can be used for such problems. The result may be a little awkward, but if you really need fast metaprograms, this is not a bad choice. I am not an expert with TH, but what you want is pretty simple, with one catch: neither "ambiguous identifiers" nor "module names" can be fixed or quoted in any way, as far as I know, I have to put them to the strings specified as arguments to the TH function.
Here is a quick and dirty, minimal example:
{-# LANGUAGE TemplateHaskell #-} module MapModuleTH where import Language.Haskell.TH mapQual :: [String] -> String -> ExpQ mapQual ms n = listE $ map (\m -> varE . mkName $ m ++ "." ++ n) ms mapMQual :: [String] -> String -> ExpQ mapMQual ms n = appE (varE 'sequence) $ listE $ map (\m -> varE . mkName $ m ++ "." ++ n) ms
You have formulated things as “launching a function”, which is more like doing a few IO
actions, and not just collecting a list of things, so I added an option that also organizes the result.
Please note that despite the use of strings here, it is still statically typed - if the names do not exist or the types do not match, you will get the expected compile-time error just as if you wrote everything manually.
Here is a brief example of its use. Given the following:
{-# LANGUAGE TemplateHaskell #-} module MapModule where import MapModuleTH import qualified Test1 as T1 import qualified Test2 as T2 tests = do xs <- $(mapMQual ["T1", "T2"] "test") putStrLn $ "Count: " ++ show (length xs)
Assuming that other modules exist and define test
, in GHCi we can see:
> tests Test 1 Test 2 Count: 2
CA McCann
source share