如何覆盖派生的Eq实例?

时间:2016-11-16 21:47:05

标签: haskell typeclass email-verification

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

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

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

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

1 个答案:

答案 0 :(得分: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