2010-09-24 78 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