2010-03-13 15 views
2

我目前正在开发一个Haskell项目,它会根据XML规范自动测试一些函数。 XML规范给出了每个函数的参数以及该函数将提供的预期结果(参数具有许多不同类型)。我知道如何从XML中提取函数参数并使用read函数解析它们,但我还没有弄清楚如何使用我得到的参数来调用函数。使用异构参数调用Haskell函数?

我基本上想要的是读取和存储在异构列表中的参数(我目前的想法是使用Data.Dynamic类型的列表),然后调用该函数,将该异构列表作为参数列表传递。这可能吗?修改被测功能不是一种选择。

+0

是否有可能使用Haskell作为spec语言而不是XML?缺点是测试规范必须链接到源代码。 (并且你的规格必须在编译时输入,而不是运行时间...) – 2010-03-13 14:12:28

+0

嗯,也许。这当然是一个我没有考虑过的想法。谢谢。 – 2010-03-13 14:17:40

回答

2

我会建议使用哈斯克尔作为规范语言的内森的建议。 Haskell本身是与Haskell函数一起使用的最好的数据格式:-)

但是由于这是一个有趣的问题,我会假装你有一些奇怪的约束,必须使用XML。您将不得不将XML转换为真正的Haskell函数。这意味着有一些映射:

lookupFunc :: String -> ??? 

它按名称查找func。您必须手动编写此映射,或使用Template Haskell生成它。但重要的是,???不是一种类型,并且此功能需要一个实际类型。

这里有一个整洁的一个,类似的异构列表,但手头更优化的问题:

data SpecFunc = Result String | More (String -> SpecFunc) 

这是你的接口XML规范。它说,要么我已经完成,并且已经有结果(已经被字符串化了),要么我需要另一个参数来继续(将字符串转换为该函数)。 (怪异的一面注意:这被称为“自由单体(字符串 - >)” - 但monadiness与我们现在完全无关)。

现在我们可以写一个类型类转换Haskell函数到他们SpecFuncs,如果他们的类型符合我们的标准:

class HasSpecFunc a where 
    toSpecFunc :: a -> SpecFunc 

instance (Read a, HasSpecFunc b) => HasSpecFunc (a -> b) where 
    toSpecFunc f = More (\input -> toSpecFunc (f (read input))) 

... -- one of these for each one of your "primitive" result types 
instance HasSpecFunc String where 
    toSpecFunc x = Result (show x) 

使用一些邪恶的,你可不必指定每个结果类型一个实例。在文件的顶部,使重叠的情况:

{-# LANGUAGE OverlappingInstances #-} 

然后使用:

instance (Show a) => HasSpecFunc a where 
    toSpecFunc x = Result (show x) 

然后你就可以调用SpecFunc的东西,如:

-- returns Nothing if the wrong number of arguments were provided 
runSpecFunc :: SpecFunc -> [String] -> Maybe String 
runSpecFunc (Result x) [] = Just x 
runSpecFunc (More f) (x:xs) = runSpecFunc (f x) xs 
runSpecFunc _ _ = Nothing 

我希望是有道理的。但是,再次抛弃XML并使用Haskell远比这更好。

+0

当然,如果你的参数和结果的结构不仅仅是可以从/到字符串转换,而且可以用String和typeclass替换为Read/Show的表示。 – luqui 2010-03-13 18:49:49

0

使用Data.Dynamic通常是一个坏主意,因为您牺牲了GHC为您检查参数的能力。几乎总是知道类型必须支持的有效函数,因此您可以使用存在类型的列表总是

相反,是否可以构建一个数据类型来表示XML将生成的有效类型?也就是说,构建一个代表格式良好的XML参数的抽象语法的ADT。

例如,看一下JSON ADT:http://hackage.haskell.org/packages/archive/json/0.4.3/doc/html/src/Text-JSON-Types.html#JSValue

另外,使用一个存在的类型(静态)确保值支持声明他们的方法。例如,XML中的所有值都必须支持Show,因此您可以将异构列表描述为:

data XMLList = forall a。显示=>的XMLList [A])

从哈斯克尔维基一个例子:http://en.wikibooks.org/wiki/Haskell/Existentially_quantified_types#Example:_heterogeneous_lists

+0

那么如何将这种类型的列表作为参数列表传递给函数呢? – 2010-03-13 14:16:41

+0

生存在这里什么都不买。 XMLList与[String]同构,因此只需使用[String]。 – luqui 2010-03-13 18:42:35