如何使用Haskell动态调用函数

时间:2012-04-04 03:12:38

标签: haskell

我希望根据关联列表中的内容动态调用函数。

以下是半伪代码中的示例。 listOfFunctions 将传递给 callFunctions

listOfFunctions = [('function one', 'value one')
                   , ('function two', 'value two')
                   , ('function three', 'value three')]

callFunctions x = loop through functions
                  if entry found 
                  then call function with value
                  else do nothing

问题的关键在于没有循环遍历列表,而是,一旦我有了它的名字,它是如何调用函数的?

考虑此用例以进一步说明。您打开命令提示符并显示以下菜单。

  

1:编写新的vHost文件

     

2:退出

您编写新的vHost文件,但未显示新菜单

  

1:输入新指令

     

2:写文件

     

3:退出

您为vHost输入了一些新指令,现在可以编写该文件了。

程序不会盲目地写出它可能的每一个指令,而是只会写出你提供的指令。这是关联列表的用武之地。编写一个巨大的if / then / else或case语句是疯狂的。循环遍历列表会更加优雅,查找添加了哪些指令并调用函数来相应地编写它们。

因此,循环,找到一个函数名,用提供的值调用所述函数。

感谢任何可以提供帮助的人。

修改

这是我提出的解决方案(建议性的批评总是受欢迎的)。

我导出了在关联列表中编写指令的函数,因为每个提供的答案都表示只需要包含该函数即可。

funcMap = [("writeServerName", writeServerName)
           ,("writeServeralias", writeServerAlias)
           ,("writeDocRoot", writeDocRoot)
           ,("writeLogLevel", writeErrorLog)
           ,("writeErrorPipe", writeErrorPipe)
           ,("writeVhostOpen", writeVhostOpen)]

在实际写入主机的文件中,导入该文件。

我有一个名为 hostInfo 的关联列表,用于模拟将从最终用户收集的一些虚拟值以及一个名为 runFunction 的函数,该函数使用< em> edalorzo 来过滤这两个列表。通过匹配两个列表的键,我确保使用正确的值调用正确的函数。

import Vhost.Directive

hostInfo =     [("writeVhostOpen", "localhost:80")
                ,("writeServerName", "norics.com")] 

runFunctions = [f val | (mapKey, f) <- funcMap, (key, val) <- hostInfo, mapKey == key]

5 个答案:

答案 0 :(得分:16)

您可以直接在列表中包含该功能;函数是值,因此您可以在列表中按名称引用它们。一旦你将它们从列表中删除,应用它们就像func value一样简单。根本不需要涉及他们的名字。

答案 1 :(得分:8)

因为我对Haskell很陌生,所以我会冒你认为我的建议非常幼稚的风险,但无论如何它仍然存在:

let funcs = [("sum", (+3),1),("product", (*3),2),("square", (^2),4)]
[f x | (name, f, x) <- funcs, name == "sum"]

我认为它满足了问题的要求,但也许你想要的更加软化,而不是我对Haskell的限制性知识所能看到的。

答案 2 :(得分:3)

这可能有点过分(我同意ehird的推理)但你可以使用System.Eval.Haskell中的eval函数来评估带有Haskell代码的字符串。

修改

正如评论中所指出的,hint是评估带有Haskell表达式的字符串的更好选择。引用页面:

  

此库定义了一个Interpreter monad。它允许加载Haskell模块,浏览它们,使用Haskell表达式进行类型检查和评估字符串,甚至将它们强制转换为值。该库是线程安全且类型安全的(甚至是表达式对值的强制)。实际上,它是用更简单的API包装的GHC API的一个重要子集。适用于GHC 6.10.x和6.8.x

答案 3 :(得分:1)

首先我们定义我们的函数列表。这可以使用更多的机器构建,但为了示例,我只创建一个明确的列表:

listOfFunctions :: [(Int, IO ())]
listOfFunctions = [(0, print "HI")        -- notice the anonymous function
                  ,(1, someNamedFunction) -- and something more traditional here
                  ]

someNamedFunction = getChar >>= \x -> print x >> print x

然后我们可以从这个列表中选择我们想要并执行的功能:

executeFunctionWithVal :: Int -> IO ()
executeFunctionWithVal v = fromMaybe (return ()) (lookup v listOfFunctions)

并且它有效(如果您导入Data.Maybe):

Ok, modules loaded: Main.
> executeFunctionWithVal 0
"HI"
> executeFunctionWithVal 01
a'a'
'a'

答案 4 :(得分:1)

不要将函数存储为字符串,或者更确切地说,尝试存储实际函数,然后用字符串标记它们。这样你就可以直接调用这个函数。函数是第一类值,因此您可以使用指定的任何名称来调用函数。