如何覆盖派生的Eq实例?

use*_*886 2 haskell typeclass email-verification

我想知道为什么email-validate包在以下代码中派生出Eq:

data EmailAddress = EmailAddress ByteString ByteString
   deriving (Eq, Ord, Data, Typeable, Generic) 
Run Code Online (Sandbox Code Playgroud)

我的意思是,我正在使用Text电子邮件地址,直到我意识到我需要使它们不区分大小写(所以我不保存Example@ex.ampleexample@ex.ample作为2个不同的地址),所以我到这个库只是为了发现它的派生Eq.

那么,派生Eq而不是自制的不区分大小写的实例是否合理?另外,如果我要使用这个库,我怎么能提供自己的Eq实例EmailAdress呢?

Ale*_*lec 13

那么,派生Eq而不是自制的不区分大小写的实例是否合理?

那取决于你想要什么.我确信包的作者有他们的理由Eq.

另外,如果我要使用这个库,我怎么能提供我自己的Eq实例EmailAdress

你无法"覆盖"他们的实例.这种问题的通常解决方案是newtype在其上编写自己的实例的包装器:

newtype MyEmailAddress = MyEmailAddress EmailAddress
Run Code Online (Sandbox Code Playgroud)

然后你可以自由定义你自己的平等版本,可能是:

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
Run Code Online (Sandbox Code Playgroud)

虽然我在这里,但请允许我提一下你甚至可以定义一个模式同义词,它可以让一切变得更好:

{-# LANGUAGE PatternSynonyms #-}
pattern Email address domain = MyEmailAddress (EmailAddress address domain)
Run Code Online (Sandbox Code Playgroud)

然后,您可以轻松地制作其中一封电子邮件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
Run Code Online (Sandbox Code Playgroud)