如何创建多变量haskell函数? [英] How to create a polyvariadic haskell function?
问题描述
我需要一个函数,它接受任意数量的参数(所有相同类型),用它们做一些事情,然后返回一个结果.在我的特定情况下,参数列表是不切实际的.
I need a function which takes an arbitrary number of arguments (All of the same type), does something with them and afterwards gives a result back. A list of arguments is impracticable in my specific case.
当我查看 haskell 库时,我看到函数 printf
(来自模块 Text.Printf
)使用了类似的技巧.不幸的是,我无法通过查看来源来理解这种魔力.
As I looked through the haskell libs, I saw that the function printf
(from module Text.Printf
) uses a similar trick. Unfortunately, I couldn't understand that magic by looking at the source.
有人可以解释如何实现这一点,或者至少可以在一些网页/论文/任何我可以找到对此进行很好描述的地方吗?
Can somebody explain how to achieve this, or at least some webpage/paper/whatever where I could find a good description for this?
动机:
我需要这个的原因真的很简单.对于学校(计算机科学课),我们需要编写一个能够记录"数学表达式的模块,将其表示为字符串(通过为自己的数据类型编写 Num/Real/etc 的实例),并执行对其进行各种操作.
The reason I need this is really quite simple. For school (computer science class), we are required to write a module that is able to "record" a mathematical expression, express it as a string (Via writing an instance of Num/Real/etc for an own datatype), and perform various operations on it.
这个数据类型包含一个特殊的变量构造函数,它可以被一个值或任何指定的函数替换.目标之一是编写一个函数,该函数采用具有一定数量变量的表达式((Char,Rational)
类型的对)并计算表达式的结果.我们应该看看如何最好地表达函数的目标.(我的想法:该函数返回另一个函数,该函数采用与函数中定义的 var 完全一样多的参数 - 似乎是不可能的.
This datatype contains a special constructor for a variable, which may be replaced by a value or whatever by a specified function. One of the goals is to write a function, which takes such an expression with some number of variables (pairs of type (Char,Rational)
) and calculates the result of the expression. We should look at how to express the goal of the function best. (My idea: The function returns another function which takes exactly as many arguments as vars that are defined in the function - seems to be impossible).
推荐答案
printf
的关键点是能够返回字符串或函数.复制自 http://www.haskell.org/ghc/docs/6.12.2/html/libraries/base-4.2.0.1/src/Text-Printf.html、
The key points of printf
is the ability to either return a String or a function. Copied from 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)
我们可以提取出的基本结构是
and the basic structure we can extract out is
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
这篇关于如何创建多变量haskell函数?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!