You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Haskell函数非穷尽模式问题:neighbours函数实现求助

Fixing the Non-Exhaustive Patterns Issue in Your 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:

  1. The first clause neighbours [] _ = [] directly handles empty input lists, eliminating the non-exhaustive warning.
  2. 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 either a or b matches inputWord, add the corresponding tuple to the result if so, then recursively process the remaining elements. Even when rest is 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:

  • concatMap iterates over every pair in the input list.
  • The helper function checkPair checks if the current pair is linked to inputWord: if yes, it returns a singleton list with the matching tuple; if not, it returns an empty list.
  • concatMap then 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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.13 09:23:21