如何编写一个以可变参数为参数的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。 例如,我们可以使用Bounded
和Enum
(对于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