如何创建一个polyvariadic haskell函数?
我需要一个函数,它接受任意数量的参数(所有相同类型),对它们做一些事情,然后再给出结果。 在我的具体情况下,争议清单是不切实际的。
当我查看haskell库时,我看到函数printf
(来自模块Text.Printf
)使用类似的技巧。 不幸的是,我无法通过查看源代码来理解这种魔法。
有人可以解释如何实现这个目标,或者至少有一些网页/论文/无论我在哪里可以找到一个好的描述?
动机:
我需要这个的原因非常简单。 对于学校(计算机科学课程),我们需要编写一个能够“记录”数学表达式的模块,将其表达为一个字符串(通过为自己的数据类型编写一个Num / Real / etc实例),并执行对其进行各种操作。
这个数据类型包含一个特殊的变量构造函数,它可以被一个指定函数的值或其他值替换。 其中一个目标是编写一个函数,它使用一些变量(类型对(Char,Rational)
)来表达一个表达式,并计算结果。 我们应该看看如何最好地表达功能的目标。 (我的想法:该函数返回另一个函数,该函数与函数中定义的变量一样多的参数 - 似乎是不可能的)。
printf
的关键点是能够返回一个String或一个函数。 复制自http://www.haskell.org/ghc/docs/6.12.2/html/libraries/base-4.2.0.1/src/Text-Printf.html,
printf :: (PrintfType r) => String -> r
printf fmts = spr fmts []
class PrintfType t where
spr :: String -> [UPrintf] -> t
instance (IsChar c) => PrintfType [c] where
spr fmts args = map fromChar (uprintf fmts (reverse args))
instance (PrintfArg a, PrintfType r) => PrintfType (a -> r) where
spr fmts args = a -> spr fmts (toUPrintf a : args)
我们可以提取出的基本结构是
variadicFunction :: VariadicReturnClass r => RequiredArgs -> r
variadicFunction reqArgs = variadicImpl reqArgs mempty
class VariadicReturnClass r where
variadicImpl :: RequiredArgs -> AccumulatingType -> r
instance VariadicReturnClass ActualReturnType where
variadicImpl reqArgs acc = constructActualResult reqArgs acc
instance (ArgClass a, VariadicReturnClass r) => VariadicReturnClass (a -> r) where
variadicImpl reqArgs acc = a -> variadicImpl reqArgs (specialize a `mappend` acc)
例如:
class SumRes r where
sumOf :: Integer -> r
instance SumRes Integer where
sumOf = id
instance (Integral a, SumRes r) => SumRes (a -> r) where
sumOf x = sumOf . (x +) . toInteger
那么我们可以使用
*Main> sumOf 1 :: Integer
1
*Main> sumOf 1 4 7 10 :: Integer
22
*Main> sumOf 1 4 7 10 0 0 :: Integer
22
*Main> sumOf 1 4 7 10 2 5 8 22 :: Integer
59
许多人告诉你如何创建可变参数函数,但我认为在这种情况下,使用[(Char,Rational)]类型的列表实际上更好。
在关于variadic函数的wiki文章中,引用了这篇文章。 我想这是printf所做的,但我也不明白。 无论如何,这当然是一种矫枉过正,尤其是因为你的论点都是相同的类型。 把它们全部放在一个列表中。 这就是列表的好处 - 同一类型的任意数量的事物。 好吧,它不是很漂亮,但它不会比完整的多变量函数更丑。
链接地址: http://www.djcxy.com/p/43083.html上一篇: How to create a polyvariadic haskell function?
下一篇: What is polymorphism, what is it for, and how is it used?