使用PatternSynonyms为何触发非穷尽匹配警告?
为什么PatternSynonyms写法会触发非穷尽匹配警告?
你用ViewPatterns实现的BFS没有匹配警告,但改用PatternSynonyms后编译器提示非穷尽匹配,核心原因是默认的模式同义词是单向的,编译器无法推导你定义的Empty和:>能覆盖所有Sequence的可能情况。
原因拆解
- 在
ViewPatterns的写法里,你直接将序列传给Seq.viewr,编译器明确知道Seq.viewr的返回类型ViewR a只有EmptyR和(:>)两种构造器,因此能判定你的匹配是穷尽的。 - 但你定义的
Empty和:>是单向模式同义词(只有匹配方向的<−定义,没有构造方向的=定义),编译器无法将它们与Sequence的内部构造逻辑关联起来,自然会认为存在未覆盖的情况(比如内部的EmptyT构造器),从而抛出警告。
修复方案
方案一:用COMPLETE编译指示声明模式完备性
直接告诉编译器,Empty和:>这两个模式可以覆盖所有Seq.Seq a的情况,不需要额外构造逻辑:
{-# LANGUAGE PatternSynonyms #-} import qualified Data.Sequence as Seq import qualified Data.Set as Set pattern Empty :: Seq.Seq a pattern Empty <- (Seq.viewr -> Seq.EmptyR) pattern (:>) :: Seq.Seq a -> a -> Seq.Seq a pattern xs :> x <- (Seq.viewr -> xs Seq.:> x) -- 告诉编译器这两个模式覆盖所有Sequence情况 {-# COMPLETE Empty, (:>) #-} bfsPat :: Seq.Seq ((Int, Int), Int) -> Set.Set (Int, Int) -> Int bfsPat Empty _ = -1 bfsPat (coords :> (coord@(r, c), dist)) seen = -- 你的搜索逻辑
方案二:定义双向模式同义词(支持匹配和构造)
给模式同义词加上构造方向的定义,让编译器既能用它匹配,也能用来构造序列,同时自动识别其完备性:
{-# LANGUAGE PatternSynonyms #-} import qualified Data.Sequence as Seq import qualified Data.Set as Set -- 双向模式:既匹配空序列,也能构造空序列 pattern Empty :: Seq.Seq a pattern Empty = Seq.empty pattern Empty <- (Seq.viewr -> Seq.EmptyR) -- 双向模式:匹配尾部元素,也能通过尾部添加构造序列 pattern (:>) :: Seq.Seq a -> a -> Seq.Seq a pattern xs :> x <- (Seq.viewr -> xs Seq.:> x) where xs :> x = xs Seq.|> x bfsPat :: Seq.Seq ((Int, Int), Int) -> Set.Set (Int, Int) -> Int bfsPat Empty _ = -1 bfsPat (coords :> (coord@(r, c), dist)) seen = -- 你的搜索逻辑
内容的提问来源于stack exchange,提问作者thisisrandy
相关产品推荐
相关产品推荐

