如何编写以变量函数为参数的Haskell函数

如何编写以变量函数为参数的Haskell函数,haskell,lambda,variadic-functions,Haskell,Lambda,Variadic Functions,我试图创建一个函数,它得到一个变量函数作为参数,即 我怎样才能做到这一点 我已经读过,并且我确信,但是,我在尝试将模式应用于变量函数作为参数的函数时迷失了方向。特别是Olegs方法似乎只适用于格拉斯哥扩展,我希望该解决方案适用于纯Haskell 98(就像这样) 我问的原因是我试图构建一个以布尔函数为参数的函数,并检查它是否是重言式,即 isTautology :: (Bool -> ... -> Bool) -> Bool 这样就可以输入: isTautology (\x

我试图创建一个函数,它得到一个变量函数作为参数,即

我怎样才能做到这一点

我已经读过,并且我确信,但是,我在尝试将模式应用于变量函数作为参数的函数时迷失了方向。特别是Olegs方法似乎只适用于格拉斯哥扩展,我希望该解决方案适用于纯Haskell 98(就像这样)

我问的原因是我试图构建一个以布尔函数为参数的函数,并检查它是否是重言式,即

isTautology :: (Bool -> ... -> Bool) -> Bool
这样就可以输入:

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

我的问题是,我一直在阅读有关将返回类型设置为类型变量(以便它可以是结果或另一个函数)的技巧,但我的返回类型是固定的(Bool)。

技巧是创建一个类型类,为其定义函数实例和返回类型实例。事实上,这是一个
Bool
根本不是问题

我们试图编写一个函数,它接受一个可变参数并返回一个
Bool
,因此我们将用这样一个函数定义一个类型类

class Stmt a where
    tautology :: a -> Bool
接下来,我们为可变函数的返回类型定义一个实例。在本例中,这是
Bool

-- A Bool is a tautology if it's True.
instance Stmt Bool where
    tautology = id
关键部分是接受
Bool
参数的函数的下一个实例,其返回类型是我们类中的某个类型。这样,如果一个函数接受多个参数,该实例将被应用多次

-- 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
。要对pure Haskell 98执行同样的操作,我们需要使用一个适当约束的类型变量。例如,我们可以使用
Bounded
Enum
(对于
Bool
,两者都有实例),或者您可以创建自己的类,让您构造适当的输入

instance (Enum a, Bounded a, Stmt b) => Stmt (a -> b) where
    tautology f = all (tautology . f) [minBound .. maxBound]
我们完成了。让我们试一下:

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

你想坚持使用Haskell 98有什么具体原因吗?GHC实际上是目前唯一认真维护的Haskell编译器。@DanBurton我实际上是一名助教,课程既不允许我介绍新奇的东西,也不允许学生(第一学期)深入研究Haskell 98的扩展。我目前正在准备这个练习。一定要坚持标准,但要与时俱进,坚持Haskell 2010。@DanielFischer Haskell 2010中没有任何东西在这种情况下对我有太大帮助,或者我错过了什么?(据我所知,Haskell 2010主要是关于语法和标准化hugs和GHC的事实行为?)是的,H2010和H98对这个问题没有影响。但是H98没有分层模块,并且有(n+k)模式。从GHC 7.2开始,程序包或程序不能同时依赖haskell98和base(至少不能没有扭曲)。自GHC 7.0以来,默认情况下禁用NPlusKPatterns。坚持使用H98会给学习者带来不愉快的体验。哇,这是一个非常优雅的解决方案。为了证明它对varargs有效:
tautology$\x->x | |而不是x
> tautology $ \x y -> (not x && not y) == not (x && y)
False
> tautology $ \x y -> (not x && not y) == not (x || y)
True