Equality

Travis CI Codacy Badge Codacy Badge

Project Goals

Equality brings a better equals in the form of ==== which prints, in case of error, a tree representation of the divergence between the compared values.

Quick Start

To use equality in an existing SBT project with Scala 2.12, add the following dependency to your build.sbt:

resolvers += Resolver.bintrayRepo("io-monadplus", "maven")

libraryDependencies += "io.monadplus" %% "equality-core" % "0.0.1"

Example

Equality is thought to be used with scalatest.

import org.scalatest.FreeSpec
import cats.implicits._
import equality.all._

class Example extends FreeSpec {
  "Given an arbitrary ADT" - {
    "should compare two instances" in {
      
      sealed trait Establishment
      case class Pub(name: String) extends Establishment
      case class Restaurant(name: String, clientsPerTable: List[Option[Int]]) extends Establishment
      case class Owner(name: String, establishment: Establishment)

      val toscana = Restaurant("Toscana", List(none, 2.some, 3.some))
      val andrea = Owner(name = "Andrea", establishment = toscana)
      
      val piazza = Restaurant("Piazza", List(none, 2.some, 4.some))
      val mario = Owner(name = "Mario", establishment = piazza)

      andrea ==== mario
    }
  }
}
scala> (new Example()).execute()
Example:
Given an arbitrary ADT
- should compare two instances *** FAILED ***
   Owner$1
       ├──  name: String [Andrea not equal to Mario]
       └──  establishment: Restaurant
                                 ├──  name: String [Toscana not equal to Piazza]
                                 └──  clientsPerTable: List
                                                          ├──  0: None
                                                          ├──  1: Some
                                                                    └──  value: Integer [2]
                                                          └──  2: Some
                                                                     └──  value: Integer [3 not equal to 4] (eq.scala:18)

Create your own instances

Equality is powered by shapeless for type class derivation of arbitrary ADTs. Equality can derive instances of products (case classes) and coproducts (sealed traits + subclasses) of any combination of primitive type. It also supports scala’s std collection like Option, List, Vector, Map, Set, et cetera.

Furthermore, a user can define its own instances in case of need.

In this example we are going to create an instance for NonEmptyList

import equality._
import equality.all._
import cats.data.NonEmptyList

implicit def nonEmptyListEq[A: Eq]: Eq[NonEmptyList[A]] = 
  new Eq[NonEmptyList[A]] {
    override def compare(x: NonEmptyList[A], y: NonEmptyList[A]) =
      Named(className = "NonEmptyList", fields = List(
        "head" -> (x.head =><= y.head),
        "tail" -> (x.tail =><= y.tail)
      ))
  }

Alternatives