为什么使用 PatternSynonyms 会触发非详尽匹配警告?

thi*_*ndy 4 haskell pattern-synonyms

我正在按照这个答案来学习如何在Sequences 上进行模式匹配。具体而言,假设我正在使用 a 作为队列在二维网格上实现广度优先搜索Sequence。仅使用ViewPatterns,我可能会想出如下内容:

\n
{-# LANGUAGE ViewPatterns #-}\n\nimport qualified Data.Sequence as Seq\nimport qualified Data.Set as Set\n\nbfs :: Seq.Seq ((Int, Int), Int) -> Set.Set (Int, Int) -> Int\nbfs (Seq.viewr -> Seq.EmptyR) _ = -1 -- goal not found\nbfs (Seq.viewr -> (coords Seq.:> (coord@(r, c), dist))) seen = -- search plumbing...\n
Run Code Online (Sandbox Code Playgroud)\n

根据@Cactus\'s 的回答,如果我也想使用PatternSynonyms,我想出:

\n
{-# LANGUAGE PatternSynonyms #-}\n\n...\n\npattern Empty :: Seq.Seq a\npattern Empty <- (Seq.viewr -> Seq.EmptyR)\n\npattern (:>) :: Seq.Seq a -> a -> Seq.Seq a\npattern xs :> x <- (Seq.viewr -> xs Seq.:> x)\n\nbfsPat :: Seq.Seq ((Int, Int), Int) -> Set.Set (Int, Int) -> Int\nbfsPat Empty _ = -1\nbfsPat (coords :> (coord@(r, c), dist)) seen = ...\n
Run Code Online (Sandbox Code Playgroud)\n

这些看起来对我来说是等价的,但编译器不同意:

\n
    In an equation for \xe2\x80\x98bfsPat\xe2\x80\x99:\n        Patterns not matched:\n            (Data.Sequence.Internal.Seq Data.Sequence.Internal.EmptyT)\n            (Data.Set.Internal.Bin _ _ _ _)\n            (Data.Sequence.Internal.Seq Data.Sequence.Internal.EmptyT)\n            Data.Set.Internal.Tip\n            (Data.Sequence.Internal.Seq (Data.Sequence.Internal.Single _))\n            (Data.Set.Internal.Bin _ _ _ _)\n            (Data.Sequence.Internal.Seq (Data.Sequence.Internal.Single _))\n            Data.Set.Internal.Tip\n            ...\n
Run Code Online (Sandbox Code Playgroud)\n

我错过了什么破坏了这两个公式之间的等价性,我该如何修复它?

\n

DDu*_*Dub 6

查看有关 COMPLETE pragmas 的 wiki 页面。我将引用开头:“详尽性检查器目前对模式同义词感到窒息。它们被标记为始终容易出错的模式,这意味着我们还必须始终包含包罗万象的情况以避免警告。”

简而言之,您需要提供完整的编译指示,例如:

{-# COMPLETE Empty, (:>) #-}
Run Code Online (Sandbox Code Playgroud)

  • 也许值得一提的是,当您告诉编译器哪些模式是完整的时,编译器会信任您。如果你对它撒谎,你不会在编译时收到警告,但它仍然会在运行时爆炸。 (4认同)