2012-11-18 59 views
2

我想將案例類與scalaz NonEmptyList字段進行比較。 ==euqls不起作用,我知道這是由於NonEmptyList.equals方法,它檢查比較對象是否與調用方相同。另一方面,對於NonEmptyList,scalaz ===函數可以正常工作,前提是必須在範圍內隱含Equalscase class with scalaz.NonEmptyList [A] as the member and the ===,equals,==

問題是我想讓我的案例類通用,並希望這個實例很容易比較。

如何做到這一點?

如果唯一的解決方案是提供自定義def equals(obj: Any): Boolean方法,請將其張貼在下面。

我的代碼:

object Problem { 

    case class CC[M, N](s: M, nel: NonEmptyList[N]) 

    CC(1, 2.wrapNel) == CC(1, 2.wrapNel) //false 

    CC(1, 2.wrapNel) equals CC(1, 2.wrapNel) //false 


    implicit def cCEquals[M, N] = equalA[CC[M, N]] 

    CC(1, 2.wrapNel) === CC(1, 2.wrapNel) //false 

    //override def equals(obj: Any): Boolean = ??? 
} 

回答

3

我知道這可能不會幫助你,但NonEmptyList作品equals方法有望在Scalaz 7(編輯:其實這是now fixed in Scalaz 6一樣,所以,如果你如果你願意從源代碼構建或者等待6.0.5,那麼你將會很好。)

儘管在Scalaz 6.0.4或更早的版本中,仍然有一種很自然的方法可以解決這個問題Equal - 你只需要確保你正在爲構建正確的Equal實例:

implicit def ccEqual[M: Equal, N: Equal] = 
    Equal.equalBy[CC[M, N], (M, NonEmptyList[N])] { 
    case CC(s, nel) => (s, nel) 
    } 

在這裏,我們要求這兩個MNEqual實例。編譯器然後可以爲NonEmptyList[N]構建一個Equal實例,然後爲(M, NonEmptyList[N])構建一個實例。並且有一個明顯的從CC[M, N](M, NonEmptyList[N])的映射,我們可以用Equal.equalBy變成所需的實例。

如果你願意使用通用平等MN,你可以這樣做,而不是:

implicit def ccEqual[M, N] = new Equal[CC[M, N]] { 
    def equal(a: CC[M, N], b: CC[M, N]) = 
    a.s == b.s && Equal.NonEmptyListEqual(Equal.equalA[N]).equal(a.nel, b.nel) 
} 

甚至只是:

implicit def ccEqual[M, N] = new Equal[CC[M, N]] { 
    def equal(a: CC[M, N], b: CC[M, N]) = a.s == b.s && a.nel.list == b.nel.list 
} 

隨着一點點的類型級魔法(例如通過Scalaz 7的typelevel或更容易地使用Shapeless),您可以讓編譯器爲其成員生成任何案例類的Equal實例,其實例爲Equal,自己寫出來並不難。

+0

很好的解釋。謝謝! –

相關問題