在大型代碼庫中,我想將具有帶有欄位的建構式的資料型別重構為簡單的標記記錄聯合,主要是為了更好地支持-Wincomplete-record-updates. 重要的是我不需要更改此資料型別的任何模式匹配,因此我嘗試使用記錄模式同義詞。這是一個精簡版:
{-# LANGUAGE PatternSynonyms #-}
{-# OPTIONS_GHC -Werror=incomplete-patterns #-}
-- Consider some data type with fields:
data D'
= A'
| B' { b'Int :: Int, b'String :: String }
foo' :: D' -> String
foo' A'{} = "A"
foo' B'{b'String = x} = x
-- I'd like to factor out a record containing the fields
-- without changing foo'.
data D
= A
| BTag BRec
data BRec = BRec { _bInt :: Int, _bString :: String }
pattern B :: Int -> String -> D
pattern B{ bInt, bString } = BTag (BRec bInt bString)
foo :: D -> String
foo A{} = "A"
foo B{bString = x} = x
-- I get this error:
-- Pattern match(es) are non-exhaustive
-- In an equation for ‘foo’: Patterns of type ‘D’ not matched: BTag _
-- |
-- 28 | foo A{} = "A"
-- | ^^^^^^^^^^^^^...
為什么會出現模式覆寫錯誤?我是否正確使用模式同義詞?如何獲得我想要的重構?
uj5u.com熱心網友回復:
您應該使用COMPLETEpragma:
{-# COMPLETE A, B #-}
這可以放在檔案中的任何位置,但作為一種組織性的東西,將它放在模式定義中是很有用的。值得注意的是,COMPLETE如果有多個涵蓋所有可能性的不同集合,您可以為同一型別定義多個 pragma。例如,Data.Sequence.Seq有兩個:
{-# COMPLETE (:<|), Empty #-}
{-# COMPLETE (:|>), Empty #-}
這使您可以靈活地提供可以以不同方式完成的重疊同義詞集。
至于為什么有必要的理由,GHC wiki 上的這篇文章提出了一個很好的論點:
模式同義詞是一種抽象手段,如果窮舉檢查器可以查看定義,那么 P 的實作將泄漏到錯誤訊息中。我們希望用戶能夠用模式同義詞替換真正的資料建構式,而不會引起消費者的注意。
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/517176.html
