Haskell 访问元组中的字段

Haskell 访问元组中的字段,haskell,Haskell,我在自学Haskell,虽然这是迄今为止最有启发性的经历,但我发现一些在C语言家族中很容易做到的事情仍然是个谜。这是我最基本的问题。我想要一个函数来提取一个特定字段等于给定值的元组。到目前为止,我有这个代码 withJob :: [(String, String, String)] -> String -> [String] withJob [] _ = [] withJob ((_,_,x):xs) job | job == x = x:(withJob xs job) | oth

我在自学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”)]
,但是我不知道如何访问元组,而不知道如何访问
job==x=x:(with job xs job)

使用
@
-模式:

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

为了扩展@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
,您可以直接使用它,而不是每次都重写代码模式。它不仅节省了您的时间和代码,而且通过重用已知函数,您可以让未来的程序员(包括您未来的自己!)更容易理解代码。

因此
@
可以帮助您同时引用原始表示法和扩展表示法。那非常方便。谢谢只是一个旁注:如果你没有混淆关注点并将所有内容打包在一个函数中,你就不会遇到这种情况。这里我们有两个问题:1。过滤列表,给定谓词和2。谓词本身。