如何编写一个以可变参数为参数的Haskell函数

我试图创build一个函数,获取一个可变参数作为参数 ,即

func :: (a -> ... -> a) -> a 

我怎么能做到这一点?

我读过关于polyvariadic函数 ,我敢肯定, Oleg已经做到了 ,但是我迷失了,试图将函数的模式应用到函数中,并且使用可变参数作为参数。 特别是Olegs的方法似乎只与格拉斯哥扩展工作,我希望解决scheme在纯粹的Haskell 98(如Text.Printf呢 )工作。

我问的原因是我试图build立一个函数,它将一个布尔函数作为一个参数,并检查它是否是一个重言式,即

 isTautology :: (Bool -> ... -> Bool) -> Bool 

所以你可以input:

 isTautology (\x -> x && not x) isTautology (\xy -> x && y || not y) 

我的问题是,我一直在阅读的诀窍是使返回types的typesvariables(以便它可以是结果或另一个函数),但我的返回types是固定的(Bool)。

诀窍是创build一个你将为其定义一个函数实例的types类,以及一个返回types的实例。 这是一个Bool事实上不是一个问题。

我们试图编写一个函数,它接受一个可变参数并返回一个Bool ,所以我们将定义一个带有这个函数的types类。

 class Stmt a where tautology :: a -> Bool 

接下来,我们为可变参数函数的返回types定义一个实例。 在这种情况下,这是Bool

 -- A Bool is a tautology if it's True. instance Stmt Bool where tautology = id 

关键部分是接受Bool参数的函数的下一个实例,其返回types是来自我们类的某种types。 这样,如果一个函数有多个参数,这个实例将被多次应用。

 -- A function is a tautology if it always returns a tautology. instance Stmt b => Stmt (Bool -> b) where tautology f = tautology (f True) && tautology (f False) 

以这种方式写入需要FlexibleInstances因为二次头部的Bool 。 要用纯粹的Haskell 98做同样的事情,我们需要使用一个适当约束的typesvariables。 例如,我们可以使用BoundedEnum (对于Bool都有实例),或者可以创build自己的类来构造适当的input。

 instance (Enum a, Bounded a, Stmt b) => Stmt (a -> b) where tautology f = all (tautology . f) [minBound .. maxBound] 

我们完成了。 让我们试试看:

 > tautology $ \xy -> (not x && not y) == not (x && y) False > tautology $ \xy -> (not x && not y) == not (x || y) True