Haskell函数非穷尽模式问题:neighbours函数实现求助
neighbours Function Let's break down what's going wrong here and fix it step by step.
The Root of the Problem
Your original function uses the pattern pairs@((x1,x2):xs) which only matches non-empty lists. When you pass an empty list [], there's no corresponding pattern to handle it—hence the non-exhaustive patterns warning.
When you tried replacing pairs == [] = [] with xs == [] = [], you introduced a new issue: when the list has only one element left (so xs is empty), your function immediately returns [] without checking if that last element matches inputWord. That's why it fails to process the final tuple.
Solution 1: Correct Recursive Pattern Matching
The fix is to explicitly handle the empty list case as a separate pattern, then process non-empty lists properly (checking each element before recursing):
neighbours :: [((String, String), Int)] -> String -> [(String, Int)] -- Handle empty list first (solves non-exhaustive pattern issue) neighbours [] _ = [] -- Process non-empty lists: split into the first pair and remaining elements neighbours ((a, b), weight) rest inputWord | a == inputWord = (b, weight) : neighbours rest inputWord | b == inputWord = (a, weight) : neighbours rest inputWord | otherwise = neighbours rest inputWord
How This Works:
- The first clause
neighbours [] _ = []directly handles empty input lists, eliminating the non-exhaustive warning. - The second clause matches any non-empty list: it extracts the first pair (
(a, b)), its weight, and the rest of the list. We check if eitheraorbmatchesinputWord, add the corresponding tuple to the result if so, then recursively process the remaining elements. Even whenrestis empty (i.e., we're on the last element), we still check the current pair before returning.
Solution 2: More Concise Haskell-Style Approach
If you prefer avoiding manual recursion, you can use concatMap to simplify the code while keeping the logic clear:
neighbours :: [((String, String), Int)] -> String -> [(String, Int)] neighbours pairs inputWord = concatMap checkPair pairs where checkPair ((a, b), w) | a == inputWord = [(b, w)] | b == inputWord = [(a, w)] | otherwise = []
How This Works:
concatMapiterates over every pair in the input list.- The helper function
checkPairchecks if the current pair is linked toinputWord: if yes, it returns a singleton list with the matching tuple; if not, it returns an empty list. concatMapthen concatenates all these results into a single list, giving you exactly the neighbours you need.
Test Example
For input like:
neighbours [(("foo", "bar"), 5), (("bar", "baz"), 3)] "bar"
Both solutions will correctly return:
[("foo",5), ("baz",3)]
内容的提问来源于stack exchange,提问作者Axel1999

