Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/9.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 我对构图的理解有差距,类型不匹配_Function_Haskell_Lambda_Function Composition - Fatal编程技术网

Function 我对构图的理解有差距,类型不匹配

Function 我对构图的理解有差距,类型不匹配,function,haskell,lambda,function-composition,Function,Haskell,Lambda,Function Composition,在我的代码中,我需要根据第二个元素的值对(Int,Int)列表进行排序 通过(\(\uu,a)(\uu,b)->比较a b)列表来排序是很容易的,但是我讨厌这样写lambda,我需要在代码中的一些地方使用相同的lambda 因此,我尝试创建了两个有用的函数,我最终将在以下许多地方使用它们(我在序言中找不到它们): 现在我想我可以组合一些东西传递给sortBy,而不是丑陋的“提取器”lambda。但是我不能把字体排成一行 我觉得我想用(expandPair compare)编写(fBoth snd

在我的代码中,我需要根据第二个元素的值对
(Int,Int)
列表进行排序

通过(\(\uu,a)(\uu,b)->比较a b)列表来排序是很容易的,但是我讨厌这样写lambda,我需要在代码中的一些地方使用相同的lambda

因此,我尝试创建了两个有用的函数,我最终将在以下许多地方使用它们(我在序言中找不到它们):

现在我想我可以组合一些东西传递给
sortBy
,而不是丑陋的“提取器”lambda。但是我不能把字体排成一行

我觉得我想用
(expandPair compare)
编写
(fBoth snd)
,因为
:t expandPair compare=(a,a)->排序
:t fBoth snd=(a,b)->(b,b)
。我认为这种组合的结果类型应该是排序,我可以通过排序传递给
,但它不太管用

如果我尝试按((expandPair compare)。(fBoth snd))[(1,2)、(3,4)]
排序,它会给我类型错误。但让我困惑的是,如果我对snd(1,2)(3,4)
进行
expandPair比较$fBoth,它实际上可以正常工作,并产生
LT

所以很明显,我对函数组合的某些方面不太了解。。。我得到了整个“由f=g(f(x))组成的g”,但我在这里很难让它对我起作用


或者,如果有一种更简单的方法来完成按第二个元素对成对列表进行排序的特定任务,我也很想听听。

首先,您的
expandPair
函数与
uncurry
中的
uncurry
的定义完全相同

这里的问题是,
fboth snd
接受两个参数,因此正常组合运算符不太适合此任务。但是,您可以创建一个外观非常奇怪的运算符,使您可以“组合”一个具有两个参数的函数和一个具有一个参数的函数:

(.:) :: (c -> d) -> (a -> b -> c) -> a -> b -> d
(.:) = (.).(.)
记住这一点最简单的记忆法是,一个点一侧的函数接受一个参数,其类型与接受两个参数的函数的输出类型相同,这两个参数位于两个点一侧。你可以这样写

sortBy (uncurry compare .: fboth snd) [(1, 2), (3, 4)]
现在,我要说的是,最好不要真正考虑
操作符是如何工作的,只看它的类型而不是它的定义。它经常派上用场,我经常使用它,当然我没有想到这个操作符


您还可以将其实现为

> :m +Data.Function
> sortBy (compare `on` snd) ...
-- sortBy (on compare snd) ...
但正如@mhwombat所指出的那样,
Data.Ord
在compare
上有一个名为
comparing
的别名:

> :m +Data.Ord
> sortBy (comparing snd) ...
这是我的偏好


可以让这个操作符更清楚一些:

> :t (id .: (,))
a -> b -> (a, b)
> (id .: (,)) 1 2
(1, 2)
> (fst .: (,)) 1 2
1
> (snd .: (,)) 1 2
2
> (negate .: (+)) 1 2
-3

比较您正在查看的特定情况下,功能上的应用程序来自:


请尝试通过(比较snd)列表排序
。你需要导入
数据。Ord
expandPair
uncurry
相同,它也有完全相同的定义。
fBoth
是你应该在
Lens
包中很容易找到的东西。我至少想把(.:)看作是定义为
fmap。函数函子上的fmap
。(对我来说)这是最有操作意义的。@J.Abrahamson有趣的是,你也可以将它定义为
(.:)=fmap-fmap-fmap
,它具有更一般的
(函子f,函子g)=>(a->b)->f(ga)->f(gb)
。我不完全确定它对其他函数有什么用处,但有趣的是,它可以这样定义。当你将它定义为
fmap-fmap-fmap
时,第一个
fmap
会被专门化为
()
。不过它很可爱。@bheklir例如
(fmap-fmap-fmap)succ[(“a”,1),(“b”,10)]
[(“a”,2),(“b”,11)]
。噢,我从来没有意识到逗号仍然只是一个普通的运算符。。。像
(,)12
那样使用它非常简单,没有想到要查看数据。函数
> :t (id .: (,))
a -> b -> (a, b)
> (id .: (,)) 1 2
(1, 2)
> (fst .: (,)) 1 2
1
> (snd .: (,)) 1 2
2
> (negate .: (+)) 1 2
-3
>>> :t (`on` snd)
(`on` snd) :: (b -> b -> c) -> (a, b) -> (a, b) -> c

>>> :t (compare `on` snd)
(compare `on` snd) :: Ord b => (a, b) -> (a, b) -> Ordering