Question

I am trying to learn scalaz and still new to scala (been using for a few months now). I really like the type-classes scalaz provides and trying to document the different use-cases for different features in scalaz. Right now I am having issues with the way implicts work and the way I want to do things.

Here is the code I would like to work

import scalaz._
import Scalaz._

object WhatIfIWantfFuzzyMatching extends App {

  implicit object evensEquals extends Equal[Int] {
    override def equal(left: Int, right: Int): Boolean = {
      val leftMod = left % 2
      val rightMod = right % 2
      leftMod == rightMod
    }
  }

  val even = 2
  val odd = 3

  assert(even =/= odd, "Shouldn't have matched!")

  val evenMultTwo = even * 2

  assert(even === evenMultTwo, "Both are even, so should have matched")
}

The idea is simple. For some parts of the code, I want the provided Equal[Int] from scalaz. In other parts of the code, I would like to override the Equal[Int] provided with a less strict one.

Right now I am hitting an issue where scala isn't able to figure out which implicit to use:

ambiguous implicit values:
both object evensEquals in object WhatIfIWantfFuzzyMatching of type com.gopivotal.scalaz_examples.equal.WhatIfIWantfFuzzyMatching.evensEquals.type
and value intInstance in trait AnyValInstances of type => scalaz.Monoid[Int] with scalaz.Enum[Int] with scalaz.Show[Int]
match expected type scalaz.Equal[Int]
assert(even =/= odd, "Shouldn't have matched!")
     ^

Looking at other threads on here, I see people say to just change the type so there isn't a conflict, or to only import when needed, but in the case of scalaz's === and mixing and matching different equals methods, I am not sure how to get that to work with the compiler.

Any thoughts?

EDIT: Here is a working example that lets you switch between implementations (thanks @alexey-romanov)

object WhatIfIWantToSwitchBack extends App {
  // so what if I want to switch back to the other Equals?
  object modEqualsInt extends Equal[Int] {
    override def equal(left: Int, right: Int): Boolean = {
      val leftMod = left % 2
      val rightMod = right % 2
      leftMod == rightMod
    }
  }

  implicit var intInstance: Equal[Int] = Scalaz.intInstance

  assert(2 =/= 4)

  intInstance = modEqualsInt

  assert(2 === 4)

  intInstance = Scalaz.intInstance

  assert(2 =/= 4)
}
Was it helpful?

Solution

You can just use the same name intInstance (but this means you'll lose the Monoid, Enum and Show instances).

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top