2010-09-24 82 views
13

是否有一个优雅的符号用于在Haskell中错乱地调用函数的参数?在Haskell中搞乱顺序

例如,如果你想通过一个列表中的所有元素来划分2,你可以写

map ((/) 2) [1,2,3,4,5] 

但是它似乎你需要定义一个匿名函数列表中的所有元素划分

map (\x -> x/2) [1,2,3,4,5] 

在更复杂的情况下,匿名函数很快变得笨拙。我知道在这种情况下,map((*)0.5)[1,2,3,4,5]可以正常工作,但我很想知道Haskell是否有一种更优雅的方式来调用函数的参数无序?

+0

'flip'和反引号很好,只需使用中缀函数(如delnan指出)。 – 2010-09-24 17:04:48

回答

16

在这种特殊情况下:

Prelude> map (/2) [1..5] 
[0.5,1.0,1.5,2.0,2.5] 

您不仅可以使用管道符作为普通的前缀功能,还可以部分地缀形式应用它。同样,第一个例子最好写成:map (2/) [1..5]

另外,还有flip这不是很优雅,但仍然是普通功能的最佳选择(当你不想通过反引号将它们变成中缀时) :

Prelude> let div' = (/) 
Prelude> div' 2 1 
2.0 
Prelude> flip div' 2 1 
0.5 
+0

这只适用于操作员吗?那么任意函数呢? – Gabe 2010-09-24 16:53:06

+0

@Gabe:正如FUZxxl写道的,它也可以与使用中缀的函数一起使用(通过将它们与反引号包围在一起)。我会举一个例子,但他已经提供了一个例子。 – delnan 2010-09-24 16:55:45

+0

谢谢。这是一个耻辱,没有语法,如f 1 2#4#,它具有与\ x y - > f 1 2 x 4 y相同的效果。 – hosiers 2010-09-24 17:02:29

2

为了您的第二个,拉姆达是不必要的,只要使用这样的:

map (/2) [1..5] 

形式(/ 2)简单地表示,要访问一个运营商的第二PARAM。第一个参数(2/)也是可能的。这被称为部分,是一个非常有用的黑客,不仅在代码高尔夫。您还可以使用它的前缀的功能,如果你使用它们缀:

map (`div` 2) [1..5] 

在更困难的情况下,如3点或更多的参数,你应该使用lambda表达式,因为它变得更具可读性最次。

2

我认为你正在寻找一个通用的解决方案,如方案中的cut。对?

flip函数反转函数的前2个参数。可能还有其他的功能在做类似的任务(我对Haskell不太擅长......)。

+1

'flip'不颠倒参数列表。它只是翻转前两个,考虑这个:flip(。)::(a→b)→b→c)→a→c。 -1 – fuz 2010-09-24 17:01:32

0

我最近遇到一个very similar issue我自己,我是不是能够找到比使用一个辅助函数来做到这一点以外的优雅的解决方案:

dbfunc f b c = (\a -> liftIO $ f a b c) 
deleteAllRows = do 
    ask >>= dbfunc run "delete from t1" [] 

至少这种模式是足够常见的根据华夏邓白氏认为dbfunc是可重用的。

+0

'ask >> = liftIO。 (翻转(翻转)“从t1删除”[])' – is7s 2012-06-09 00:08:49

+0

对于某些优雅的值;-) – Gaius 2012-06-15 13:23:07