如何编写一个将可变参数函数作为参数的Haskell函数 [英] How to write a Haskell function that takes a variadic function as an argument

查看:195
本文介绍了如何编写一个将可变参数函数作为参数的Haskell函数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

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

我该如何做到这一点?

我已阅读了多元函数,我相信奥列格已经做到了,但是我失去了尝试在功能上应用模式以可变参数作为参数。特别是Olegs的方法似乎只适用于格拉斯哥扩展,我希望解决方案在纯Haskell 98中工作(如 Text.Printf )。



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

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

可以输入:

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

我的问题是,我一直在阅读关于诀窍是将返回类型设置为类型变量它可以是结果或其他函数),但是我的返回类型是固定的(Bool)。 解决方案

您将为其定义函数实例的类型类,以及返回类型的实例。它是一个 Bool 这个事实根本不是问题。



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

  class Stmt a where 
tautology :: a - > Bool

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

   -  Bool是重言式,如果它是真的。 
实例stmt bool其中
tautology = id

关键部分是下一个函数的实例需要一个 Bool 参数,并且其返回类型是我们类中的某种类型。这样,如果一个函数接受多个参数,这个实例将被多次应用。

   - 一个函数是一个重复式总是返回重言式。 
实例stmt b => Stmt(Bool - > b)其中
重言式f =重言式(f真)&&重言式(f False)

这样写需要 FlexibleInstances 因为第二个实例头中的 Bool 。要用纯粹的Haskell 98做同样的事情,我们需要使用适当约束的类型变量。例如,我们可以使用 Bounded Enum (对于 Bool < code $),或者你可以创建你自己的类来让你创建适当的输入。

$ $ p $ instance(Enum a,Bounded a,Stmt b)=> Stmt(a - > b)其中
重言式f =全部(重言式。f)[minBound .. maxBound]

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

 >重言式$ \x y  - > (不是x&& not y)==不是(x&& y)
False
>重言式$ \x y - > (不是x&& not y)== not(x || y)
True


I'm trying to create a function that gets a variadic function as an argument, i.e.

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

how can I accomplish this?

I've read about polyvariadic functions and I'm sure that Oleg already did it, however I'm lost trying to apply the pattern on a function with a variadic function as an argument. Especially Olegs approach seems to work with glasgow extensions only and I want the solution to work in pure Haskell 98 (like Text.Printf does).

The reason that I ask is that I'm trying to build a function which takes a boolean function as an argument and checks whether it is a tautology, i.e.

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

so that one could type:

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

My problem is that I keep reading about the trick was to make the return type a type variable (so that it can be the result or another function), but my return type is fixed (Bool).

解决方案

The trick is to make a type class for which you will define an instance for functions, and an instance for the return type. The fact that it's a Bool is not a problem at all.

We're trying to write a function which takes a variadic argument and returns a Bool, so we'll define a type class with such a function.

class Stmt a where
    tautology :: a -> Bool

Next, we define an instance for the return type of the variadic function. In this case, that's Bool.

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

The key part is the next instance for functions that take a Bool argument, and whose return type is some type from our class. That way, this instance will be applied multiple times if a function takes multiple arguments.

-- 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)

Writing it this way requires FlexibleInstances because of the Bool in the second instance head. To do the same with pure Haskell 98, we'll need to use a suitably-constrained type variable instead. We can for example use Bounded and Enum (there are instances for both for Bool), or you can make your own class that will let you construct the appropriate inputs.

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

And we're done. Let's try it out:

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

这篇关于如何编写一个将可变参数函数作为参数的Haskell函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆