访问元组中的字段

时间:2013-04-02 18:37:13

标签: haskell

我正在教自己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")],但是我不知道如何访问元组而不是工作({{ 1}})x

2 个答案:

答案 0 :(得分:8)

使用@ - 模式:

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

答案 1 :(得分: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,人们可以使用它,而不是每次都重写这种代码模式。它不仅可以节省您的时间和代码,而且通过重用已知函数,您可以让未来的程序员更容易理解代码(包括您未来的自我!)