zio/zio-prelude

NewTypes 과 Equal 을 활용한 객체 비교

wefree 2021. 9. 23. 23:25

문제

다음과 같이 Site, bookSite, newsSite 를 정의할 때

final case class Site(domain: String, url: String)

val bookSite = Site("naver.com", "http://book.naver.com")
val newsSite = Site("naver.com", "http://news.naver.com")

bookSite 와 newsSite 를

  • domain 기준으로 비교하면 같다.
  • url 기준으로 비교하면 다르다.

domain 과 url 기준으로 각각 비교하는 method 를 아래처럼 추가할 수 있지만

final case class Site(domain: String, url: String) {
  def equalByDomain(other: Site): Boolean = domain == other.domain
  def equalByUrl(other: Site): Boolean    = url == other.url
}

zio-prelude 의 NewTypesEqual 을 사용해 구현해 보도록 한다. (이렇게 구현하면 어떤 장점이 있을까?)

 

코드

import zio.prelude.{Equal, EqualOps, Subtype}

object EqualTest {
  final case class Site(domain: String, url: String)

  object EqualByDomain extends Subtype[Site] {
    implicit val equalByDomain = new Equal[EqualByDomain] {
      override protected def checkEqual(l: EqualByDomain, r: EqualByDomain): Boolean = 
        l.domain == r.domain
    }
  }
  type EqualByDomain = EqualByDomain.Type

  object EqualByUrl extends Subtype[Site] {
    implicit val equalByUrl: Equal[EqualByUrl] = 
      (l: EqualByUrl, r: EqualByUrl) => l.url == r.url
  }
  type EqualByUrl = EqualByUrl.Type

  def main(args: Array[String]): Unit = {
    val bookSite = Site("naver.com", "http://book.naver.com")
    val newsSite = Site("naver.com", "http://news.naver.com")

    val byDomain = EqualByDomain(bookSite) === EqualByDomain(newsSite)
    println(byDomain)  // true

    val byUrl = EqualByUrl(bookSite) === EqualByUrl(newsSite)
    println(byUrl)     // false
  }
}