如何用任意一个函数构成`not`? [英] How to compose `not` with a function of arbitrary arity?

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

问题描述

当我有一些像

类型的函数时,b
$ b

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

我应该使用函数来包装这个函数而不是。



例如make function like this

  g ::(Ord a)=> a  - > a  - > Bool 
gab = not $ fab

我可以制作combinator,比如

  nf =(\ a  - > \b  - >不是$ fab)

但我不知道如何。

  * Main>让n f =(\ a→b→b→b)不是$ f a b)
n ::(t→t1→Bool)→> t - > t1 - > Bool
Main> :t n f
n f ::(Ord t)=> t - > t - > Bool
* Main>让g = n f
g ::() - > () - > Bool

我做错了什么?

和奖金问题,我怎么能做到这一点与更多和最少参数的功能例如

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


解决方案

除非你想要用类型类来破解,这是更好的思想实验和概念验证,你只是不推广到多个参数。不要尝试。

至于你的主要问题,这是用Conal Elliott的语义编辑组合器最优雅的解决方案。语义编辑器组合器是一个类型如下的函数:

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

其中 F(x)是涉及 x 的表达式。还有一些逆变编辑器组合器,它们取(b - > a)。直观上,编辑器组合器选择一些较大值的一部分进行操作。你需要的是 result

  result =(。) 

查看您尝试操作的表达式的类型:

  a  - > a  - > Bool 

此类型的结果(codomain)为 a - > Bool ,并且结果 类型是 Bool ,这就是你想要应用的不是到。因此,要将 not 应用于函数 f 的结果,可以这样写:

 (result.result)不是f 

这很好地概括。这里有几个combinator:

$ $ p $ argument = flip(。) - contravariant

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

left f(Left x)= Left(fx)
左f(右x)=右x
...

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

  Int  - >或者(String  - >(Int,Bool))[Int] 



  不是到Bool,您只需拼出路径即可: 

 (result.left.result.second)不是x 

哦,如果你已经函子还没有,你会注意到 fmap 是一个编辑器组合器。实际上,上面可以拼写:

$ $ $ $ $ $ $ $ $ $ $ $ $ $ $
$ code>

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



享受。


When I have some function of type like

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

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

e.g. make function like this

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

I can make combinator like

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

But I don't know how.

*Main> let n f = (\a -> \b -> 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

What am I doing wrong?

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.

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)

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

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

So if you have a value x of type:

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

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

(result.left.result.second) not x

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.

Enjoy.

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

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