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