2012-04-04 40 views
7

我正在寻找基于关联列表中找到的内容动态调用函数。如何使用Haskell动态调用函数

这里是一个半伪码的例子。 listOfFunction将传递给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:编写新的虚拟主机文件

2:退出

你写新的虚拟主机文件,而不是一个新的菜单呈现

1:输入新指令

2:写入文件

3:退出

您为vHost输入了一些新指令,现在已准备好写入该文件。

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

因此,循环,找到一个函数名称,使用提供的值调用该函数。

感谢任何能够帮助您的人。

编辑:

这里是我想出来的(建设性的批评总是受欢迎的)解决方案。

我导出了在关联列表中写入指令的函数,因为提供的每个答案都表示只包含该函数就是要走的路。

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

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

我有称为Hostinfo中的关联列表,以模拟将来自终端用户收集一些虚值和一个函数调用runFunction使用由edalorzo供给通过两个列表来过滤技术。通过匹配两个列表的键,我确保使用正确的值调用正确的函数。

​​

回答

8

作品因为我farily新哈斯克尔我将风险你考虑我的建议很幼稚,但反正这里有云:

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

我认为这满足了这个问题的要求,但也许你打算比我用Haskell知识有限的知识更加复杂。

16

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

+0

我知道你对答案有更多的投票,但是,因为我结束了使用edalorzo的代码,我接受了他的答案。 – OpCodeOmega 2012-04-06 02:31:33

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' 
+0

请注意,在这种情况下,该列表实际上不包含任何功能;只是'IO'行动。 – ehird 2012-04-04 03:22:33

+0

任何人都在关注他们的投票吗? – 2012-04-04 14:55:10

1

的功能不要存放为字符串,或者更确切地说,试图存储实际的功能,然后用一个字符串标记它们。这样你就可以直接调用这个函数。函数是第一类的值,所以你可以使用你指定的名字来调用函数。

2

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

编辑

正如在评论中指出,hint是哈斯克尔表达式计算字符串的一个更好的选择。引用页面:

该库定义了一个Interpreter monad。它允许加载Haskell模块,浏览它们,使用Haskell表达式检查和评估字符串,甚至将它们强制转换为值。该库是线程安全的和类型安全的(即使表达式强制为值)。它本质上是一个封装在一个更简单的API中的GHC API的巨大子集。与GHC 6.10.x和6.8.x

+0

插件自2010年以来未更新,并且不适用于最近的GHC;如果你需要在运行时解释Haskell代码,[提示](http://hackage.haskell.org/package/hint)是一个更好的选择。 – ehird 2012-04-04 03:36:55

+0

@谢谢!我用你的建议更新了我的答案。 – 2012-04-04 03:41:50

+1

@ehird有人在几天前宣布,“插件”处于新的维护模式下,新版本应该在几天内发布。虽然它还没有结束。 – 2012-04-04 08:04:32