Haskell 动态模块名

Haskell 动态模块名,haskell,module,Haskell,Module,我想在Haskell中做类似的事情,但编译器不允许我这样做 有没有办法完成这项任务 -- both modules export function named "hello" -- and I want to run it in every module import qualified MyMod as M1 import qualified MyAnotherMod as M2 runmodules = map (\m -> m.hello) [M1, M2] 我不认为您可以在模板

我想在Haskell中做类似的事情,但编译器不允许我这样做

有没有办法完成这项任务

-- both modules export function named "hello"
-- and I want to run it in every module
import qualified MyMod as M1
import qualified MyAnotherMod as M2

runmodules = map (\m -> m.hello) [M1, M2]

我不认为您可以在模板haskell中引用这样的限定名称前缀,而且
hello
标识符不在范围内,因此您可能不得不退回到使用字符串编程

module ModuleParamsTH where
import Language.Haskell.TH

getAll :: String -> [String] -> ExpQ
getAll valueName moduleNames = 
  listE $ map (varE . mkName . (++ suffix)) moduleNames
  where suffix = "." ++ valueName
然后可以这样使用

{-# LANGUAGE TemplateHaskell #-}
import ModuleParamsTH
import qualified ModuleParamsM1 as M1
import qualified ModuleParamsM2 as M2

runmodules = $(getAll "hello" ["M1", "M2"])

然而,我不会做所有这些。您可以编写
[M1.hello,M2.hello]
或使用类型类对实现进行抽象。

模块不是Haskell中的值。因此,这是不可能的。您想要实现什么?

恐怕Haskell中的模块甚至都不是这方面所需要的一流实体

然而,正如bzn所评论的,可以用于此类问题。结果可能有点笨拙,但如果你真的需要一些快速的元编程技巧,这不是一个坏选择。我并不是TH方面的专家,但您想要的是非常简单的,有一个问题:据我所知,“模糊标识符”和“模块名称”都不能以任何方式被捕获或引用,因此您必须将它们放入作为TH函数参数的字符串中

下面是一个简单、快速的示例:

{-# 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
您将事情表述为“运行函数”,这听起来更像是执行一系列
IO
操作,而不仅仅是收集一系列内容,因此我添加了一个变体,它还对结果进行排序

注意,尽管这里使用了字符串,但它仍然是静态类型的——如果限定名不存在,或者类型不匹配,您将得到预期的编译时错误,就像您手工写出所有内容一样

下面是一个使用它的快速示例。鉴于以下情况:

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

你想解决什么问题?既然函数名是已知的(hello),为什么不把函数放在一个列表中
[M1.hello,M2.hello]
?我想你可以用TemplateHaskell解决问题,但这可能太复杂了。
> tests
Test 1
Test 2
Count: 2