2016-11-16 131 views
2

我想知道爲什麼email-validate包在下面的代碼推導公式:如何重寫派生的Eq實例?

data EmailAddress = EmailAddress ByteString ByteString 
    deriving (Eq, Ord, Data, Typeable, Generic) 

我的意思是,我是用Text電子郵件地址,直到我意識到我需要讓他們不區分大小寫(所以我不」 t保存[email protected][email protected]作爲2個不同的地址),所以我到這個庫只發現它派生Eq

那麼,推導出Eq而不是自制的不區分大小寫的實例是否合理呢? 另外,如果我要使用這個庫,我怎麼能提供我自己的Eq實例爲EmailAdress

+3

你可能會考慮使用標準化的情況下,而不是使用原始'EmailAddress'構造一個聰明的構造函數。 – chepner

+3

@chepner ...或雙向模式同義詞。然後甚至可以模式匹配。 – Alec

回答

13

那麼,推導出Eq而不是自制的不區分大小寫的實例是否合理呢?

這種取決於你想要什麼。我相信該軟件包的作者有他們的理由爲Eq實例。

另外,如果我要使用這個庫,我怎麼能提供我自己的Eq實例EmailAdress

你不能「覆蓋」他們的實例。通常解決這類問題是,你寫你自己的情況下,一個newtype包裝:

newtype MyEmailAddress = MyEmailAddress EmailAddress 

然後你可以自由定義自己平等的版本,可能是由於:

import Data.Char (toLower) 
import qualified Data.ByteString.Char8 as DBC (map) 

instance Eq MyEmailAddress where 
    MyEmailAddress (EmailAddress a1 d1) == MyEmailAddress (EmailAddress a2 d2) 
    = DBC.map toLower a1 == DBC.map toLower a2 && DBC.map toLower d1 == DBC.map toLower d2 

,而我在這,讓我提你甚至可以定義圖案代名詞,這使得一切都好得多:

{-# LANGUAGE PatternSynonyms #-} 
pattern Email address domain = MyEmailAddress (EmailAddress address domain) 

然後,您可以使用Email "yourName" "yourDomain"輕鬆製作您的一封電子郵件,以及模式匹配。該Eq情況看起來更好了很多與此:

instance Eq MyEmailAddress where 
    Email a1 d1 == Email a2 d2 
    = DBC.map toLower a1 == DBC.map toLower a2 && DBC.map toLower d1 == DBC.map toLower d2 
+1

我想補充一點,你可以使用'GeneralizedNewtypeDeriving'來保留你想要的'EmailAddress'的任何實例。 –

+0

@AlexeyRomanov我真的很激烈辯論我是否也想添加一些關於這個的東西。我想我不會這麼做,因爲OP已經提供了EmailAddress的全部數據定義,並且沒有任何東西需要使用GND來提升。 – Alec