Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/8.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Function 如何用任意算术的函数组合'not'?_Function_Haskell_Functional Programming_Composition - Fatal编程技术网

Function 如何用任意算术的函数组合'not'?

Function 如何用任意算术的函数组合'not'?,function,haskell,functional-programming,composition,Function,Haskell,Functional Programming,Composition,当我有某种类型的函数时,比如 f :: (Ord a) => a -> a -> Bool f a b = a > b 我想做一个函数,它用not来包装这个函数 e、 g.使函数像这样 g :: (Ord a) => a -> a -> Bool g a b = not $ f a b 我可以让combinator像 n f = (\a -> \b -> not $ f a b) 但我不知道怎么做 *Main> let n f =

当我有某种类型的函数时,比如

f :: (Ord a) => a -> a -> Bool
f a b = a > b
我想做一个函数,它用not来包装这个函数

e、 g.使函数像这样

g :: (Ord a) => a -> a -> Bool
g a b = not $ f a b
我可以让combinator像

n f = (\a -> \b -> not $ f a b)
但我不知道怎么做

*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
我做错了什么

还有一个额外的问题是,对于参数更多、最少的函数,我如何做到这一点

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

您的n组合符可以写为:

n = ((not .) .)
关于奖金问题,典型的解决方法是创建以下几个问题:

lift2 = (.).(.)
lift3 = (.).(.).(.)
lift4 = (.).(.).(.).(.)
lift5 = (.).(.).(.).(.).(.)
等等。

关于:我做错了什么

我认为您的combinator很好,但当您让它在顶层绑定时,Haskell的一个恼人的“默认规则”开始发挥作用,绑定并不是通用的:

Prelude> :ty (n f)
(n f) :: (Ord t) => t -> t -> Bool
Prelude> let g = n f
Prelude> :ty g
g :: () -> () -> Bool
我想你可能会被“单态限制”搞砸,因为它适用于类型类。在任何情况下,如果您退出顶级循环,并将内容放入具有显式类型签名的单独文件中,那么一切都可以正常工作:

module X where

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

g :: Ord a => a -> a -> Bool
g = n f

奖励问题:要使用越来越多的类型参数,您可以尝试使用类型类系统玩坏血病把戏。要查阅的两篇论文是Hughes、Claessen和Ralf Hinze的论文。

除非你想去破解类型类,这最好留给思考实验和概念证明,否则你就不能概括为多个论点。不要尝试

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

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

result = (.)
查看您试图操作的表达式的类型:

a -> a -> Bool
这种类型的结果(codomain)是
a->Bool
,而这种类型的结果是
Bool
,这就是您试图应用
而不是
的内容。因此,要将
not
应用于函数
f
的结果,您需要编写:

(result.result) not f
这是一个很好的概括。这里还有几个组合器:

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

Int -> Either (String -> (Int, Bool)) [Int]
如果你想将
而不是
应用到Bool,你只需说出到达那里的路径:

(result.left.result.second) not x
哦,如果你已经了解了函子,你会注意到,
fmap
是一个编辑器组合器。事实上,上述内容可以拼写为:

(fmap.left.fmap.fmap) not x
但我认为使用扩展名称更为清晰


享受。

事实上,对类型类执行任意算术非常简单:

module Pred where

class Predicate a where
  complement :: a -> a

instance Predicate Bool where
  complement = not

instance (Predicate b) => Predicate (a -> b) where
  complement f = \a -> complement (f a)  
  -- if you want to be mysterious, then
  -- complement = (complement .)
  -- also works

ge :: Ord a => a -> a -> Bool
ge = complement (<)
模块Pred,其中
类谓词a where
补语::a->a
实例谓词Bool where
补充=不
实例(谓词b)=>谓词(a->b),其中
补码f=\a->补码(f a)
--如果你想变得神秘,那么
--补语=(补语。)
--也有效
通用电气:作战需求文件a=>a->a->Bool

ge=complete(它在ghci中也起作用。让g:(Ord a)=>(a->a->Bool);g=n F在
(谓词b)=>谓词(a->b)
)中有一个看似自由的
a
是一个愉快而有用的想法。使用SEC符号,您还可以将函数的实例编写为complete=result-complete,这相当于Norman的“神秘”版本,写得不那么神秘/更规则。这是否依赖于函数的同构性?例如,我如何使用类型类定义“比较器”"1..n个元组的函数,它给出了第一个元组
uncurry compare$Tm
的结果,其中结果不是
EQ
?@Dominic:我想我不理解你的问题。但是它适用于任何返回
Bool
的函数,不管参数的类型是什么。异构类型的参数很好。例如,给定
成员::Eq a->a->a->[a]->Bool
补码成员
正是您所期望的。对;我没有解释得那么好。假设我想对类型类执行“任意算术”但是typeclass中定义的函数不是
a->a
,而是做了一些其他的事情。一个简单的例子是一个计算其参数的任意算术函数。我显然写不出来:class Count a where Count::a->Int Count=1 instance(Count b)=>Count(a->b)where Count=1+(Count(未定义::b))的预期效果是
count 1=>1
count 1'a'Nothing=>3
。GHC抱怨
b
在最后一行中含糊不清。我喜欢这种对秒的解释。更多信息,请参阅。小更正:我称
不是
编辑器和<代码>结果<代码> >代码>左,<代码>第二版/代码>等“编辑器组合器”,因为它们将编辑器转换成一个组合。考虑将.NET-tag添加到右面板上的有趣标签;或者作为result.result,result.result.result,等等,你可以穿插其他的SECs,比如first,second和fmap。我怀疑这仅仅是函数组合符号的中缀,使人们不认为它是一元的,因此可以以这种强大的方式进行组合。