我正在研究一個小的重構,其中涉及將數據類型的一部分從Int
類型轉換爲新類型包裝。之前:是否有可能使用類型系統或不同的設計來捕捉這個錯誤?
data Account = Account {
accountId :: Int
} deriving (Eq, Show)
後:
newtype AccountId = AccountId Int deriving (Eq, Ord, Read, Show)
data Account = Account {
accountId :: AccountId
} deriving (Eq, Show)
在我傳遞accountId
到功能,從第三方庫的目的,程序的其他部分過濾它返回的結果。然而,過濾器預計Text
輸入,並accountId
轉換成我使用了以下內容:
Text.pack $ show $ accountId someAccount
這導致錯誤的結果Show
實例("123"
VS "AccountId 123"
)重構後在運行時返回由於差異。
有沒有一種方法,無論是利用類型系統或不同的方式來轉換成Text
,這將在編譯時捕捉到這一點?想到的一個解決方案是定義一個幫助函數,該函數採用accountId someAccount
的結果並將其轉換爲Text
,但也許存在我不知道的不同/更好的選項/模式。
通過定義自動定義的'Show'和'Read'實例,你在技術上完全打破了抽象 - 這就是你正在觀察的。如果你公開一個'Show'實例,它應該是例如'show(AccountId x)= show x'。請注意'Eq'和'Ord'確實沒有這樣的問題。 – user2407038
最好不要依靠'show'來自行提供您的需求指定的字符串表示。定義一個專用的'AccountId - > Text'函數。另請參見:[* Haskell:show和pretty-print instance *](http://stackoverflow.com/q/8217511/2751851)。 – duplode
在您通過將您的值轉換爲字符串來繞過它之前,類型系統*確實*防止了此錯誤。 – user2297560