SML函数匹配非穷尽问题:如何处理遗漏的嵌套列表情况?
Hey there! Let's tackle that annoying Warning: match nonexhaustive message you're seeing. The issue is that your current function doesn't account for all possible nested list structures the compiler might encounter—even if you know your input will only have single-element sublists, the compiler can't assume that, so it flags unhandled cases.
Let's Break Down the Problem with Your Original Code
Your function looks like this:
fun inner_list [[]] = [] | inner_list [] = [] | inner_list ((((x:(string*real))::xt)::xs)) = x :: inner_list xs;
The gaps in pattern matching are:
- Cases where a sublist is empty but isn't the only element in the outer list (like
[[], ("foo", ~10.0)]) - Cases where a sublist has more than one element (even if you don't expect this, the compiler needs a pattern for it)
Solution 1: Tailored to Your Input Constraints
Since you mentioned your input only contains sublists with a single element (or empty ones), we can adjust the function to explicitly handle these cases without extra fluff. Here's the fixed version:
fun inner_list [] = [] | inner_list ([] :: rest) = inner_list rest // Skip empty sublists entirely | inner_list (((x : string*real) :: _) :: rest) = x :: inner_list rest;
- The first clause handles an empty outer list (same as before).
- The second clause skips any empty sublists and continues processing the rest of the outer list—this covers the
[[], ...]case the compiler was complaining about. - The third clause uses
_instead ofxt(since you don't need the rest of the sublist) and works for any sublist with at least one element, which eliminates the warning about unhandled multi-element sublists.
Solution 2: A More General Flattener (Just in Case!)
If you ever need to handle sublists with multiple elements and fully flatten them (like turning [[("a",1.0), ("b",2.0)], [("c",3.0)]] into [("a",1.0), ("b",2.0), ("c",3.0)]), here's a more flexible version that has no matching warnings:
fun flatten [] = [] | flatten ((elem :: sub_rest) :: outer_rest) = elem :: flatten (sub_rest :: outer_rest) | flatten ([] :: outer_rest) = flatten outer_rest;
This recursively processes every element in every sublist, ensuring all possible nested list structures are covered.
Why This Works
By explicitly accounting for empty sublists (regardless of where they appear) and using _ to ignore unused parts of sublists, we eliminate all unhandled cases the compiler was flagging. Now your function will work as expected for your input and pass the compiler's checks without warnings.
内容的提问来源于stack exchange,提问作者vesii

