Haskell报错[-Wincomplete-patterns]解决:模式匹配非详尽问题排查
修复Haskell中minBy函数的非详尽模式匹配错误
错误原因
你的minBy函数只覆盖了两种列表模式:包含至少两个元素的(x:y:xs)和单元素列表[x],完全没有处理空列表[]。而编译选项-Werror=incomplete-patterns会将这种未覆盖所有可能输入的模式匹配视为编译错误,因此抛出了提示。
修复方案
根据业务需求,有三种常见的处理方式:
1. 抛出异常(适合明确不会传入空列表的场景)
直接为空列表添加模式匹配,用error抛出明确的错误信息:
minBy :: Ord b => (a -> b) -> [a] -> a minBy measure list = case list of [] -> error "minBy: 不能传入空列表" (x:y:xs) -> minBy measure (if measure x > measure y then y:xs else x:xs) [x] -> x
这种方式简单直接,但如果调用方传入空列表会导致程序崩溃,仅适合能保证输入列表非空的场景。
2. 返回Maybe类型(更安全的惯用方式)
调整函数返回类型为Maybe a,空列表时返回Nothing,有有效元素时返回Just a,强制调用方显式处理空列表的情况:
minBy :: Ord b => (a -> b) -> [a] -> Maybe a minBy measure list = case list of [] -> Nothing (x:y:xs) -> minBy measure (if measure x > measure y then y:xs else x:xs) [x] -> Just x
对应的测试代码需要同步调整,匹配Maybe类型的返回值:
testMinBy :: Test testMinBy = TestCase $ do assertEqual "test1" (minBy (\x -> -x) [1,2,3,4,5]) (Just 5) assertEqual "test2" (minBy length ["a", "abcd", "xx"]) (Just "a") -- 可选:添加空列表的测试用例 assertEqual "test empty list" (minBy id []) Nothing
3. 传入默认值(让调用方决定空列表的处理逻辑)
修改函数签名,增加一个默认值参数,空列表时返回该默认值:
minBy :: Ord b => a -> (a -> b) -> [a] -> a minBy defaultValue measure list = case list of [] -> defaultValue (x:y:xs) -> minBy defaultValue measure (if measure x > measure y then y:xs else x:xs) [x] -> x
调用时需要传入空列表对应的默认值,例如:
-- 空列表时返回0 minBy 0 (\x -> -x) []
内容的提问来源于stack exchange,提问作者user20556088
相关产品推荐
相关产品推荐

