diverging implicit expansion - scala

Can someone please explain to me why I get a 'diverging implicit expansion error' here? I think it has to do with the type synonym type MyIdType = String but I am not sure why.
import org.scalacheck.Arbitrary
import org.scalacheck.Arbitrary._
import org.scalacheck.Gen
def arbitraryCaseClass[A,C](f: A => C)(implicit t: Arbitrary[A]): Arbitrary[C] = Arbitrary(for(v <- arbitrary[A]) yield f(v))
type MyIdType = String
implicit val arbMyIdType: Arbitrary[MyIdType] = Arbitrary(Gen.identifier)
case class Foo(s: MyIdType, t: Int)
implicit def arbA = arbitraryCaseClass((Foo.apply _).tupled)
val foo = arbitrary[Foo].sample
error:
Error:(13, 40) diverging implicit expansion for type org.scalacheck.Arbitrary[(A$A6.this.MyIdType, Int)]
starting with method arbTuple2 in trait ArbitraryArities
implicit def arbA = arbitraryCaseClass((Foo.apply _).tupled)

Related

How to correctly use ambiguous implicits for type negation in Scala

Ultimately what I want to do is provide one implementation of a type class for some specific type T and another implementation for all other types which are not T. I thought (perhaps incorrectly) that the easiest way to do this would be to try type negation via ambiguous implicits as described in this question. However, if I accidentally omit the implicit type class declaration, my code will still compile (should it?) but include bugs as only one of the implementations is used.
This is how the context bound is defined:
scala> trait NotAnInt[A]
defined trait NotAnInt
scala> implicit def everythingIsNotAnInt[A]: NotAnInt[A] = new NotAnInt[A] {}
everythingIsNotAnInt: [A]=> NotAnInt[A]
scala> implicit def intsAreInts1: NotAnInt[Int] = ???
intsAreInts1: NotAnInt[Int]
scala> implicit def intsAreInts2: NotAnInt[Int] = ???
intsAreInts2: NotAnInt[Int]
scala> implicit def nothingsAreInts1: NotAnInt[Nothing] = ???
nothingsAreInts1: NotAnInt[Nothing]
scala> implicit def nothingsAreInts2: NotAnInt[Nothing] = ???
nothingsAreInts2: NotAnInt[Nothing]
At this point NotAnInt[T] is summonable for all T except Int/Nothing:
scala> implicitly[NotAnInt[String]]
res3: NotAnInt[String] = $anon$1#1a24fe09
scala> implicitly[NotAnInt[Int]]
<console>:16: error: ambiguous implicit values:
both method intsAreInts1 of type => NotAnInt[Int]
and method intsAreInts2 of type => NotAnInt[Int]
match expected type NotAnInt[Int]
implicitly[NotAnInt[Int]]
^
scala> implicitly[NotAnInt[Nothing]]
<console>:18: error: ambiguous implicit values:
both method nothingsAreInts1 of type => NotAnInt[Nothing]
and method nothingsAreInts2 of type => NotAnInt[Nothing]
match expected type NotAnInt[Nothing]
implicitly[NotAnInt[Nothing]]
^
Now I have my NotAnInt context bound defined I can create my type class with its implementations:
scala> trait IntChecker[A] { def isInt(): Boolean }
defined trait IntChecker
scala> implicit val intIntChecker: IntChecker[Int] = new IntChecker[Int] { override def isInt = true }
intIntChecker: IntChecker[Int] = $anon$1#585dd35c
scala> implicit def otherIntChecker[A: NotAnInt]: IntChecker[A] = new IntChecker[A] { override def isInt = false }
otherIntChecker: [A](implicit evidence$1: NotAnInt[A])IntChecker[A]
This type class can be used as expected:
scala> def printIntStatus[T: IntChecker](t: T): Unit = { println(implicitly[IntChecker[T]].isInt()) }
printIntStatus: [T](t: T)(implicit evidence$1: IntChecker[T])Unit
scala> printIntStatus(3)
true
scala> printIntStatus("three")
false
However, the following also compiles:
scala> def printIntStatusWithBug[T](t: T): Unit = { println(implicitly[IntChecker[T]].isInt()) }
printIntStatusWithBug: [T](t: T)Unit
scala> printIntStatusWithBug(3)
false
scala> printIntStatusWithBug("three")
false
I would not expect this second function to compile as there should be no implicit IntChecker[T] available. I expect everythingIsNotAnInt is the cause of this problem but I can't think of a way around this.
I'm interested in why this approach fails as well as alternative methods on how to achieve the same thing. Thank you.
Consider the following alternative implementation (which uses Sabin's type inequalities)
trait =!=[A, B]
implicit def neq[A, B] : A =!= B = null
implicit def neqAmbig1[A] : A =!= A = null
implicit def neqAmbig2[A] : A =!= A = null
trait IntChecker[A] {
def isInt(): Boolean
}
object IntChecker {
import scala.reflect.ClassTag
implicit val intIntChecker: IntChecker[Int] = () => true
implicit def notIntIntChecker[T: ClassTag](implicit ev: T =!= Int): IntChecker[T] = () => false
}
def printIntStatus[T: IntChecker](t: T) = implicitly[IntChecker[T]].isInt()
import IntChecker._
printIntStatus(3)
printIntStatus("three")
which outputs
res0: Boolean = true
res1: Boolean = false
however the buggy implementation where we forget IntChecker bound
def printIntStatusWithBug[T](t: T) = implicitly[IntChecker[T]].isInt()
should not compile due to having T: ClassTag bound in
implicit def notIntIntChecker[T: ClassTag](implicit ev: T =!= Int)
giving compiler error
could not find implicit value for parameter e: IntChecker[T]
def printIntStatusWithBug[T](t: T) = implicitly[IntChecker[T]].isInt()
^

Scala implicit conversion(String to a custom class and its subclass)

Here's the code,
trait TestBase{}
class TestA(str:String) extends TestBase
class TestB(str:String) extends TestBase
class TestC(str:String) extends TestBase
implicit def mystr2TestA(str:String):TestA = {println(str);null.asInstanceOf[TestA]}
implicit def mystr2TestB(str:String):TestB = {println(str);null.asInstanceOf[TestB]}
implicit def mystr2TestC(str:String):TestC = {println(str);null.asInstanceOf[TestC]}
val testA:TestA = "abc"
val testB:TestB = "abc"
val testC:TestC = "abc"
Question is how to create the implicit conversion from String to TestBase and its subclass with more elegant and efficient code?(Maybe just one implicit function?) This is the Code I run in Scala REPL
You could rewrite this as one implicit def like this.
implicit def conv[A <: TestBase](str: String): A = {println(str); null.asInstanceOf[A] }
But depending on what you are really trying to, there might be a better solution than converting all Strings to any TestBase.
EDIT:
For some reason Scala doesn't seem to consider the type constraint when selecting the implicit conversion. It gets even weirder:
scala> implicit def bla2Test[A](str: String)(implicit ev: A <:< TestBase): A = null.asInstanceOf[A]
warning: there were 1 feature warning(s); re-run with -feature for details
bla2Test: [A](str: String)(implicit ev: <:<[A,TestBase])A
scala> val notTest: NotTest = "str"
notTest: NotTest = null
scala> implicitly[NotTest <:< TestBase]
<console>:15: error: Cannot prove that NotTest <:< TestBase.
implicitly[NotTest <:< TestBase]
^
So the compiler supplies an instance of NotTest <:< TestBase to bla2Test but no instance exists.
And when you want to inspect the type A:
scala> import scala.reflect.runtime.universe._
import scala.reflect.runtime.universe._
scala> implicit def bla2Test[A <: TestBase](str: String)(implicit tag: TypeTag[A]): A = { println(tag); null.asInstanceOf[A] }
warning: there was one feature warning; re-run with -feature for details
bla2Test: [A <: TestBase](str: String)(implicit tag: reflect.runtime.universe.TypeTag[A])A
scala> val notTest: NotTest = "str"
<console>:21: error: type mismatch;
found : String("str")
required: NotTest
val notTest: NotTest = "str"
^
scala> val notTest: TestBase = "str"
<console>:20: error: macro has not been expanded
val notTest: TestBase = "str"
^

Marshalling of `Map`s with Spray

I have been trying to marshal a bunch of Maps but I get error. Here is the definitions:
import spray.httpx.SprayJsonSupport._
import spray.json.DefaultJsonProtocol._
import scala.collection.JavaConverters._
case class SchemaMap( schemaMap: scala.collection.immutable.Map[String, Integer] ) /** FIRST ERROR IS HERE!! **/
case class Profile( counts: scala.collection.immutable.Map[String, SchemaMap] )
case class Profiles( profiles: scala.collection.immutable.Seq[Profile] )
object Profiles {
implicit val schemaMapMarshall = jsonFormat1(SchemaMap.apply)
implicit val profileMarshall = jsonFormat1(Profile.apply)
implicit val profilesMarshall = jsonFormat1(Profiles.apply)
def convertAProfileToScala(javaProfile: edu.illinois.cs.cogcomp.profilerNew.model.Profile): Profile = {
val out = javaProfile.getAllSchema.asScala.map{item =>
(item._1, SchemaMap(item._2.asScala.toMap))
}.toMap
Profile(out)
}
def convert[Profiles](sq: collection.mutable.Seq[Profiles]): collection.immutable.Seq[Profiles] =
collection.immutable.Seq[Profiles](sq:_*)
def convertProfilesToScala(javaProfiles: java.util.List[edu.illinois.cs.cogcomp.profilerNew.model.Profile]): Profiles = {
val a: collection.mutable.Seq[Profile] = javaProfiles.asScala.map{ convertAProfileToScala }
val immutableSeq = collection.immutable.Seq[Profile](a:_*)
Profiles(immutableSeq)
}
}
Here is the error:
Error:(16, 47) could not find implicit value for evidence parameter of type spray.json.DefaultJsonProtocol.JF[scala.collection.immutable.Map[String,Integer]]
implicit val schemaMapMarshall = jsonFormat1(SchemaMap.apply)
^
Error:(16, 47) not enough arguments for method jsonFormat1: (implicit evidence$1: spray.json.DefaultJsonProtocol.JF[scala.collection.immutable.Map[String,Integer]], implicit evidence$2: ClassManifest[org.allenai.example.webapp.SchemaMap])spray.json.RootJsonFormat[org.allenai.example.webapp.SchemaMap].
Unspecified value parameters evidence$1, evidence$2.
implicit val schemaMapMarshall = jsonFormat1(SchemaMap.apply)
^
Error:(17, 45) could not find implicit value for evidence parameter of type spray.json.DefaultJsonProtocol.JF[scala.collection.immutable.Map[String,org.allenai.example.webapp.SchemaMap]]
implicit val profileMarshall = jsonFormat1(Profile.apply)
^
Error:(17, 45) not enough arguments for method jsonFormat1: (implicit evidence$1: spray.json.DefaultJsonProtocol.JF[scala.collection.immutable.Map[String,org.allenai.example.webapp.SchemaMap]], implicit evidence$2: ClassManifest[org.allenai.example.webapp.Profile])spray.json.RootJsonFormat[org.allenai.example.webapp.Profile].
Unspecified value parameters evidence$1, evidence$2.
implicit val profileMarshall = jsonFormat1(Profile.apply)
^
Error:(18, 46) could not find implicit value for evidence parameter of type spray.json.DefaultJsonProtocol.JF[scala.collection.immutable.Seq[org.allenai.example.webapp.Profile]]
implicit val profilesMarshall = jsonFormat1(Profiles.apply)
^
Error:(18, 46) not enough arguments for method jsonFormat1: (implicit evidence$1: spray.json.DefaultJsonProtocol.JF[scala.collection.immutable.Seq[org.allenai.example.webapp.Profile]], implicit evidence$2: ClassManifest[org.allenai.example.webapp.Profiles])spray.json.RootJsonFormat[org.allenai.example.webapp.Profiles].
Unspecified value parameters evidence$1, evidence$2.
implicit val profilesMarshall = jsonFormat1(Profiles.apply)
^
NOTE: there is a similar post here, but the answer didn't help here. As you can see I already have the imports suggested in its answer and have all the variables immutable.
One error at a time. The problem here is that your map is using Integer, which Spray doesn't know how to map. If you use Int then it will work:
scala> case class SchemaMap( schemaMap: scala.collection.immutable.Map[String, Integer] )
defined class SchemaMap
scala> val schemaMapMarshall = jsonFormat1(SchemaMap.apply)
<console>:12: error: could not find implicit value for evidence parameter of type spray.json.DefaultJsonProtocol.JF[scala.collection.immutable.Map[String,Integer]]
scala> case class SchemaMap( schemaMap: scala.collection.immutable.Map[String, Int])
defined class SchemaMap
scala> val schemaMapMarshall = jsonFormat1(SchemaMap.apply)
schemaMapMarshall: spray.json.RootJsonFormat[SchemaMap] = spray.json.ProductFormatsInstances$$anon$1#53e166ad
Alternately you can define your own JsonFormat[Integer].

Arranging implicits precedence in Scala

Consider the following (working) snippet that defines bidirectional implicit conversions between the DenseVector and Arrays:
import scala.reflect.ClassTag
import org.apache.spark.mllib.linalg.Vectors
import breeze.linalg.{DenseVector => BDV}
implicit def bdvToSeq[T](vect: BDV[T])(implicit ct: ClassTag[T]): Seq[T] = vect.toArray.toSeq
implicit def arrayToVect(darr: Array[Double]): BDV[Double]
= new BDV(darr)
implicit def bdvToArray[T](vect: BDV[T])(implicit ct: ClassTag[T]): Array[T] = vect.toArray
def add(v1: BDV[Double], v2: BDV[Double]) =
v1.zip(v2).map { x => x._1 + x._2}
Let's try it out:
scala> arr.allVisitableIndicesActive // Array to DenseVector implicit conversion
res4: Boolean = true
scala> val d = new BDV(Array(77.7, 88.8, 99.9))
d: breeze.linalg.DenseVector[Double] = DenseVector(77.7, 88.8, 99.9)
Now the other direction:
scala> def myArrMethod(arr: Array[Double]) = println(arr.mkString(","))
myArrMethod: (arr: Array[Double])Unit
scala> myArrMethod(d) // DenseVector to array conversion
77.7,88.8,99.9
The following also works: notice the darr.toSeq
def norm(darr: Array[Double]): Double = {
Math.sqrt(darr.toSeq.foldLeft(0.0) { case (sum, dval) => sum + Math.pow(dval, 2)})
}
However if we omit the .toSeq then we have implicits collision:
scala> def norm(darr: Array[Double]): Double = {
Math.sqrt(darr.foldLeft(0.0) { case (sum, dval) => sum + Math.pow(dval, 2)})
}
<console>:34: error: type mismatch;
found : darr.type (with underlying type Array[Double])
required: ?{def foldLeft(x$1: ? >: Double(0.0)): ?}
Note that implicit conversions are not applicable because they are ambiguous:
both method doubleArrayOps in object Predef of type (xs: Array[Double])scala.collection.mutable.ArrayOps[Double]
and method arrayToVect of type (darr: Array[Double])breeze.linalg.DenseVector[Double]
are possible conversion functions from darr.type to ?{def foldLeft(x$1: ? >: Double(0.0)): ?}
Math.sqrt(darr.foldLeft(0.0) { case (sum, dval) => sum + Math.pow(dval, 2)})
^
<console>:34: error: value foldLeft is not a member of Array[Double]
Math.sqrt(darr.foldLeft(0.0) { case (sum, dval) => sum + Math.pow(dval, 2)})
I would however prefer not to put the ".toSeq" explicitly.
So my question is: how to set the proper precedence so that the Predef.toSeq is the clear winner - always tried before the custom lower priority implicits defined above?
You can extract all your implicit conversions into object, and import them only where needed
trait BDVImplicits {
implicit def bdvToSeq[T](vect: BDV[T])(implicit ct: ClassTag[T]): Seq[T] =
vect.toArray.toSeq
implicit def arrayToVect(darr: Array[Double]): BDV[Double] =
new BDV(darr)
implicit def bdvToArray[T](vect: BDV[T])(implicit ct: ClassTag[T]): Array[T] =
vect.toArray
}
object BDVImplicits extends BDVImplicits
If you'll place your 'norm' method in Utils for example, and don't import implicit you'll be good. You'll just need to import BDVImplicits._ in class where you call your Util methods.
I think it's simplest workaround for this problem.

Can't find Traverse for sequencing Seq[ValidationNel[String, MyCaseClass]] => ValidationNel[String, Seq[MyCaseClass]]

I have some code like the following:
import scalaz._
import Scalaz._
case class Foo(i: Int)
type ValidatedNel[A] = ValidationNel[String, A]
val foos: Seq[ValidatedNel[Foo]] = Seq(Success(Foo(1)), Success(Foo(2)), Failure(NonEmptyList("3 failed")), Failure(NonEmptyList("4 failed")))
val validated: ValidatedNel[Seq[Foo]] = foos.sequence[ValidatedNel, Foo]
This fails during compilation with this error:
Error:(51, 50) could not find implicit value for parameter F0: scalaz.Traverse[Seq]
val validated: ValidatedNel[Seq[Foo]] = foos.sequence[ValidatedNel, Foo]
Error:(51, 50) not enough arguments for method ToTraverseOps: (implicit F0: scalaz.Traverse[Seq])scalaz.syntax.TraverseOps[Seq,scalaz.package.ValidationNel[String,Foo]].
Unspecified value parameter F0.
val validated: ValidatedNel[Seq[Foo]] = foos.sequence[ValidatedNel, Foo]
I'd like to get an end result like this in the example I gave:
val validated = Failure(NonEmptyList("3 failed", "4 failed"))
If foos had only Success and no Failure, I'd like to see the simple sequence of them: Success(Foo(1), Foo(2)).
Why am I getting the compile failure I mentioned? As far as I understand it, this should work based on the types.
Is this related to the type aliasing unpacking to something like A[B[C[D], E]] => B[C[D, A[E]] instead of A[B[C]] => B[A[C]]?
AFAIK, there is no instance of Traverse[Seq] in scalaz. You may replace the Seq by a List or convert it, or implement Traverse[Seq] (implicit val seqInstance: Traverse[Seq] = ???).
import scalaz._
import Scalaz._
case class Foo(i: Int)
type ValidatedNel[A] = ValidationNel[String, A]
val foos: List[ValidatedNel[Foo]] = List(Success(Foo(1)), Success(Foo(2)), Failure(NonEmptyList("3 failed")), Failure(NonEmptyList("4 failed")))
val validated: ValidatedNel[List[Foo]] = foos.sequence[ValidatedNel, Foo]