2013-04-02 51 views
4

我在教自己的Haskell,雖然迄今爲止這是一個非常有啓發性的經驗,但我發現C語言家族很容易完成的一些事情仍然是一個謎。所以,這是我非常基本的問題。我想要一個函數來提取具有與給定值相等的特定字段的元組。到目前爲止,我有這樣的代碼訪問元組中的字段

withJob :: [(String, String, String)] -> String -> [String] 
withJob [] _ = [] 
withJob ((_,_,x):xs) job 
| job == x = x:(withJob xs job) 
| otherwise = (withJob xs job) 

users :: [(String, String, String)] 
users = [("Jack", "22", "Programmer"), ("Mary", "21", "Designer"), ("John", "24", "Designer")] 

當這樣調用users 'withJob' "Programmer"它輸出["Programmer"]但我想它想輸出[("Jack", "22", "Programmer")],但我不知道如何訪問的元組,而不是作業(x)在job == x = x:(withJob xs job)

+1

只是一個方面說明:你不會碰到這個你沒有混淆擔憂,並將所有內容都包含在一個函數中。這裏我們有兩個問題:1.過濾一個列表,給出一個謂詞,以及2.謂詞本身。 – Ingo

回答

8

使用@ -patterns爲:

withJob :: [(String, String, String)] -> String -> [(String, String, String)] 
withJob [] _ = [] 
withJob ([email protected](_,_,x):xs) job 
    | job == x = t : withJob xs job 
    | otherwise =  withJob xs job 
+1

所以'@'可以幫助您對原始表示和擴展表示都有參考。這太方便了。謝謝! – Meda

+0

只有這樣不檢查... – MtnViewMark

+1

@MtnViewMark謝謝。固定簽名。 –

4

要展開什麼@Ingo漸漸的:這將是更地道的Haskell寫:

jobField :: (String, String, String) -> String 
jobField (_, _, j) = j 

withJob :: [(String, String, String)] -> String -> [(String, String, String)] 
withJob xs job = filter (\x -> jobField x == job) xs 

我們可以走得更遠:

data Person = Person { pName :: String, pAge :: Int, pJob :: String } 

filterbyJob :: String -> [Person] -> [Person] 
filterbyJob job xs = filter (\p -> pJob p == job) xs 

即使如此:

filterbyJob :: String -> [Person] -> [Person] 
filterbyJob job = filter (\p -> pJob p == job) 

甚至:

filterbyJob :: String -> [Person] -> [Person] 
filterbyJob job = filter ((== job) . pJob) 

在這一點上,除非是要使用filterByJob可怕的是,它可能沒有提供超出實際價值只需在您需要的地方寫上filter ((== job) . pJob)

這個練習的要點是,有一個強大的功能filter,人們可以使用它,而不是每次重寫該模式的代碼。它不僅可以節省時間和代碼,而且通過重用已知函數,使代碼更容易被未來的程序員理解(包括您未來的自我!)