2010-06-28 60 views

回答

73

作爲參數higher order functions(以函數作爲參數的函數),您希望某些特定值保持不變的參數很有用。

實施例1:單獨留下值,如果它是在一個只是,否則,返回7.

Prelude Data.Maybe> :t maybe 
maybe :: b -> (a -> b) -> Maybe a -> b 

Prelude Data.Maybe> maybe 7 id (Just 2) 
2 

實施例2的默認值:通過摺疊建立的函數:

Prelude Data.Maybe> :t foldr (.) id [(+2), (*7)] 
:: (Num a) => a -> a 

Prelude Data.Maybe> let f = foldr (.) id [(+2), (*7)] 

Prelude Data.Maybe> f 7 
51 

我們使用id作爲基本案例,通過摺疊功能列表構建了一個新功能f

示例3:函數爲monoids(簡化)的基函數。

instance Monoid (a -> a) where 
     mempty  = id 
     f `mappend` g = (f . g) 

我們與倍例子類似,函數可以被視爲concatenable值,其中id服務於空的情況下,並且如(.)追加。

例4:一個平凡的散列函數。

Data.HashTable> h <- new (==) id :: IO (HashTable Data.Int.Int32 Int) 

Data.HashTable> insert h 7 2 

Data.HashTable> Data.HashTable.lookup h 7 
Just 2 

哈希表需要散列函數。但是如果你的密鑰已經被散列了呢?然後傳遞id函數,作爲你的哈希方法填充,零性能開銷。

+0

它會更好使用'與foldl」(。)id'了'foldr相似(。)id'? – 2010-06-28 22:52:17

+2

不是在這種情況下。嚴格性對功能構成沒有任何影響。 – 2010-06-28 23:10:56

+0

@Don Stewart,我希望編譯器在某些函數(比如'(+)'和其他需要同時綁定兩個參數的外部函數)上做一些可怕的錯誤,比如改變應用程序樹來摺疊一些節點並釋放它們使用的內存。 – ony 2010-06-29 06:46:21

16

在函數式語言中,函數是您可以作爲參數傳遞的第一類值 。 因此id最常見的用途之一出現時, 您將一個函數作爲 參數傳遞給另一個函數,告訴它該怎麼做。 做什麼的選擇之一很可能是 「就這麼一個人」 - 在這種情況下,您通過id 作爲參數。

+0

'只留下它'是使我點擊的部分,謝謝! – Whitebird 2015-08-10 18:46:01

3

對於不同種類的回答:

通過組成鏈接多個功能時,我會經常這樣做:

foo = id 
    . bar 
    . baz 
    . etc 

foo = bar 
    . baz 
    . etc 

它使事情變得更容易編輯。我們可以做類似的事情與其他「零」的元素,如

foo = return 
    >>= bar 
    >>= baz 

foos = [] 
    ++ bars 
    ++ bazs 
+4

聰明,但你真的*在真實的代碼中做到這一點?這幾乎讓我渴望Java。 – jrockway 2010-06-28 23:54:59

+0

如果組合不適合整齊排列在一行上,則以真實代碼形式執行此操作。這通常發生在函數名稱很長和/或有許多有意義的參數時。 – 2010-06-29 00:52:55

62

如果操作數字,特別是加法和乘法,你會注意到的0和1的實用性同樣,如果你操作列表,空列表變得非常方便。同樣,如果你操作函數(在函數式編程中很常見),你會注意到與id相同的有用性。

+1

先生,我只花了一次閱讀來理解'id'。謝謝。 – yeyo 2016-01-26 23:03:39

4

假設您正在尋找某種解決方案,以便在每次轉身時進行移動。您從候選職位pos開始。在每個階段都有一個可能會對pos進行轉換的列表(例如在拼圖中滑動一塊)。在函數式語言中,將轉換表示爲函數是很自然的,所以現在您可以使用函數列表創建一個移動列表。如果「無所事事」在這個難題中是合法的舉動,那麼你會用id來代表這一點。如果你沒有這樣做,那麼你需要處理「無所事事」作爲與「做某事」不同的特殊情況。通過使用id,您可以在一個列表中統一處理所有情況。

這可能是爲什麼幾乎所有的用途id存在的原因。用「做事」統一處理「無所事事」。

0

每當你需要某個地方有一個函數,但想要做的不僅僅是保持它的位置(以'undefined'爲例)。

這也是有益的,因爲(即將成爲)斯圖爾特博士上面提到的,當你需要通過一個函數作爲參數傳遞給另一個函數:

join = (>>= id) 

或作爲的結果功能:

let f = id in f 10 

(想必,你以後會修改上面的函數做一些更「有趣」 ......;)

正如其他人所說,id是韓元當你需要一個功能的地方時,這是一個有害的地方。

3

我也可以幫助提高你的高爾夫比分。除了使用

($)

,你可以通過使用ID保存單個字符。

例如

zipWith id [(+1), succ] [2,3,4]

一個有趣的,不是有用的結果更多。

+0

在QWERTY鍵盤上鍵入($)也很痛苦,所以我非常沉迷於儘可能使用ID。 – mrehayden 2011-08-17 19:19:47

+1

如果空白計數,它將無濟於事。 'zipWith($)[] []'與'zipWith id [] []'。 – Artyom 2012-07-25 13:52:47

3

由於我們正在尋找好的應用程序id。在這裏,迴文:)

import Control.Applicative 

pal :: [a] -> [a] 
pal = (++) <$> id <*> reverse 
+1

哇,有人可以解釋這是如何工作的? – 2013-09-04 13:23:46

+1

@MiguelRodrigues here :)'<*> reverse' suggest應用實例(( - >)r)'其中'(f <*> g)x = fx(gx)'和'($)=(。)'so so pal x =((++).id)x(reverse x)= x ++ reverse x'。 (這表示'pal =(++)<*> reverse'也有效)。 – 2014-10-05 14:58:45

2

想象一下,你是一臺電腦,即你可以執行一系列步驟。然後,如果我希望你保持目前的狀態,但我總是要給你一個指示(我不能只是靜音,讓時間過去),我會給你什麼指示? Id是爲此創建的函數,用於返回參數不變(在前一臺計算機的情況下,參數將是其狀態)併爲其命名。只有當你擁有高階函數時,當你使用函數而不考慮它們內部的東西時,這種必然性纔會出現,這迫使你以象徵的方式表達甚至「無所作爲」的實現。類似地0被看作是某種東西的數量,是沒有數量的象徵。實際上在代數0和ID被認爲是操作的分別的中性元素+和∘(功能組合物),或更正式:

爲類型數所有的x:

  • 0 + X = X
  • X + 0 = X

類型函數的所有F:

  • ID∘˚F= F
  • ˚F∘ID = F