如何用任意数量的函数组合`not`? [英] How to compose `not` with a function of arbitrary arity?

查看:22
本文介绍了如何用任意数量的函数组合`not`?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当我有一些类似的功能时

When I have some function of type like

f :: (Ord a) => a -> a -> Bool
f a b = a > b

我想要用 not 包装这个函数的 make 函数.

I should like make function which wrap this function with not.

例如制作这样的功能

g :: (Ord a) => a -> a -> Bool
g a b = not $ f a b

我可以制作类似的组合器

I can make combinator like

n f = (a ->  -> not $ f a b)

但我不知道怎么做.

*Main> let n f = (a ->  -> not $ f a b)
n :: (t -> t1 -> Bool) -> t -> t1 -> Bool
Main> :t n f
n f :: (Ord t) => t -> t -> Bool
*Main> let g = n f
g :: () -> () -> Bool

我做错了什么?

还有一个额外的问题,我如何为具有更多和最少参数的函数执行此操作,例如

And bonus question how I can do this for function with more and lest parameters e.g.

t -> Bool
t -> t1 -> Bool
t -> t1 -> t2 -> Bool
t -> t1 -> t2 -> t3 -> Bool

推荐答案

除非您想对类型类进行黑客攻击,否则最好将其留给思想实验和概念证明,否则您只是不要概括为多个参数.不要尝试.

Unless you want to go hacking around with typeclasses, which is better left for thought experiments and proof of concept, you just don't generalize to multiple arguments. Don't try.

至于您的主要问题,Conal Elliott 的语义编辑器组合器最优雅地解决了这个问题.语义编辑器组合器是一个函数,其类型如下:

As for your main question, this is most elegantly solved with Conal Elliott's semantic editor combinators. A semantic editor combinator is a function with a type like:

(a -> b) -> F(a) -> F(b)

其中F(x) 是一些涉及x 的表达式.还有逆变"编辑器组合器,它们采用 (b -> a) 代替.直观地说,编辑器组合器会选择某个较大值的一部分进行操作.您需要的称为 result:

Where F(x) is some expression involving x. There are also "contravariant" editor combinators which take a (b -> a) instead. Intuitively, an editor combinator selects a part of some larger value to operate on. The one you need is called result:

result = (.)

看看你试图操作的表达式的类型:

Look at the type of the expression you're trying to operate on:

a -> a -> Bool

这种类型的结果(codomain)是a ->Bool那个 类型的结果是Bool,这就是你试图应用not 的结果.因此,要将 not 应用于函数 f 的结果,您可以这样写:

The result (codomain) of this type is a -> Bool, and the result of that type is Bool, and that's what you're trying to apply not to. So to apply not to the result of the result of a function f, you write:

(result.result) not f

这很好地概括了.这里还有一些组合器:

This beautifully generalizes. Here are a few more combinators:

argument = flip (.)     -- contravariant

first f (a,b) = (f a, b)
second f (a,b) = (a, f b)

left f (Left x) = Left (f x)
left f (Right x) = Right x
...

所以如果你有一个 x 类型的值:

So if you have a value x of type:

Int -> Either (String -> (Int, Bool)) [Int]

如果你想将 not 应用到 Bool,你只需拼出到达那里的路径:

And you want to apply not to the Bool, you just spell out the path to get there:

(result.left.result.second) not x

哦,如果您已经接触过 Functors,您会注意到 fmap 是一个编辑器组合器.其实上面可以拼写:

Oh, and if you've gotten to Functors yet, you'll notice that fmap is an editor combinator. In fact, the above can be spelled:

(fmap.left.fmap.fmap) not x

但我认为使用扩展名称更清晰.

But I think it's clearer to use the expanded names.

享受.

这篇关于如何用任意数量的函数组合`not`?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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