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()
^
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"
^
How can I find out whether a type is a singleton or not?
case object Foo
case class Bar(i: Int)
def isSingleton[A](implicit t: reflect.ClassTag[A]): Boolean = ???
assert( isSingleton[Foo.type])
assert(!isSingleton[Bar ])
Do you need a ClassTag (<:< is deprecated in ClassTag)? If not, then it works this way:
scala> import scala.reflect.runtime.universe._
import scala.reflect.runtime.universe._
scala> def isSingleton[A : TypeTag] = typeOf[A] <:< typeOf[Singleton]
isSingleton: [A](implicit evidence$1: reflect.runtime.universe.TypeTag[A])Boolean
scala> isSingleton[Foo.type]
res5: Boolean = true
scala> isSingleton[Bar]
res6: Boolean = false
I want to add another possibility which is useful when you are on the level of Symbol (e.g. going down the sub types of type):
def isSingleton[A: TypeTag]: Boolean = typeOf[A].typeSymbol.isModuleClass
Intent
I am trying to add support for :kind command to scala repl. Thanks to Eugene Burmako, I was able to get a working prototype. Though it only works with fully qualified names and fails to resolve imported names.
I am now trying to use IMain.exprTyper to do the job, as it is aware of types, imported into the repl. But there is a problem. Everything I've tried returns a ClassInfoType like the following (displayed with showRaw):
ClassInfoType(List(TypeRef(TypeRef(TypeRef(TypeRef(NoPrefix(), package <root>, List()), package java, List()), package lang, List()), class Object, List()), TypeRef(TypeRef(TypeRef(NoPrefix(), package <root>, List()), package scala, List()), trait Serializable, List())), Scope{
def <init>(): Option.type;
implicit def option2Iterable(xo: Option): Iterable;
def apply(x: Object): Option;
def empty(): Option;
private def readResolve(): Object
}, object Option)
While the working implementation returns specific Type:
PolyType(List(TypeName("A")), ClassInfoType(List(TypeRef(ThisType(scala), TypeName("AnyRef"), List()), TypeRef(ThisType(scala), scala.Product, List()), TypeRef(ThisType(scala), scala.Serializable, List())), Scope(nme.CONSTRUCTOR, TermName("isEmpty"), TermName("isDefined"), TermName("get"), TermName("getOrElse"), TermName("orNull"), TermName("map"), TermName("fold"), TermName("flatMap"), TermName("flatten"), TermName("filter"), TermName("filterNot"), TermName("nonEmpty"), TermName("withFilter"), TypeName("WithFilter"), TermName("contains"), TermName("exists"), TermName("forall"), TermName("foreach"), TermName("collect"), TermName("orElse"), TermName("iterator"), TermName("toList"), TermName("toRight"), TermName("toLeft")), scala.Option))
Question
I feel like I'm really close. Here's a playground, you can use to try everything yourself:
Welcome to Scala version 2.11.0-20130328-093148-47645c7e7e (OpenJDK 64-Bit Server VM, Java 1.7.0_17).
Type in expressions to have them evaluated.
Type :help for more information.
scala> import scala.reflect.runtime.universe._
import scala.reflect.runtime.universe._
scala> import scala.tools.nsc.interpreter.IMain
import scala.tools.nsc.interpreter.IMain
scala> val mirror = runtimeMirror(getClass.getClassLoader) // Working approach
mirror: reflect.runtime.universe.Mirror = JavaMirror with scala.tools.nsc.interpreter.IMain$TranslatingClassLoader#3d34ec98 of type class scala.tools.nsc.interpreter.IMain$TranslatingClassLoader with classpath [<unknown>] and parent being scala.tools.nsc.util.ScalaClassLoader$URLClassLoader#5d990e8c of type class scala.tools.nsc.util.ScalaClassLoader$URLClassLoader with classpath [file:/usr/lib/jvm/java-7-openjdk/jre/lib/resources.jar,file:/usr/lib/jvm/java-7-openjdk/jre/lib/rt.jar,file:/usr/lib/jvm/java-7-openjdk/jre/lib/jsse.jar,file:/usr/lib/jvm/java-7-openjdk/jre/lib/jce.jar,file:/usr/lib/jvm/java-7-openjdk/jre/lib/charsets.jar,file:/usr/lib/jvm/java-7-openjdk/jre/lib/rhino.jar,file:/home/folone/workspace/scala-myfork/build/pack/lib/jline.jar,file:/home/folone/workspace/scala-myfork...
scala> val typer = new IMain().exprTyper // Not working approach
typer: scala.tools.nsc.interpreter.IMain#exprTyper.type = scala.tools.nsc.interpreter.IMain$exprTyper$#68c181f0
scala> val expr = "scala.Option"
expr: String = scala.Option
scala> showRaw(mirror.staticClass(expr).toType.typeSymbol.typeSignature) // Correct signature
res6: String = PolyType(List(TypeName("A")), ClassInfoType(List(TypeRef(ThisType(scala), TypeName("AnyRef"), List()), TypeRef(ThisType(scala), scala.Product, List()), TypeRef(ThisType(scala), scala.Serializable, List())), Scope(nme.CONSTRUCTOR, TermName("isEmpty"), TermName("isDefined"), TermName("get"), TermName("getOrElse"), TermName("orNull"), TermName("map"), TermName("fold"), TermName("flatMap"), TermName("flatten"), TermName("filter"), TermName("filterNot"), TermName("nonEmpty"), TermName("withFilter"), TypeName("WithFilter"), TermName("contains"), TermName("exists"), TermName("forall"), TermName("foreach"), TermName("collect"), TermName("orElse"), TermName("iterator"), TermName("toList"), TermName("toRight"), TermName("toLeft")), scala.Option))
scala> showRaw(typer.typeOfExpression(expr).typeSymbol.typeSignature) // Wrong signature
res7: String =
ClassInfoType(List(TypeRef(TypeRef(TypeRef(TypeRef(NoPrefix(), package <root>, List()), package java, List()), package lang, List()), class Object, List()), TypeRef(TypeRef(TypeRef(NoPrefix(), package <root>, List()), package scala, List()), trait Serializable, List())), Scope{
def <init>(): Option.type;
implicit def option2Iterable(xo: Option): Iterable;
def apply(x: Object): Option;
def empty(): Option;
private def readResolve(): Object
}, object Option)
How do I transform ClassInfoType into a valid Type containing the needed info? Alternatively, how do I get the Type using IMain in the first place?
How about this? I'm using power mode which gives you access to the global from the currently running REPL, which is a shade more convenient than creating a new IMain.
scala> :power
Already in power mode.
scala> val g = global
g: $r.intp.global.type = <global>
scala> val context = g.analyzer.rootContext(NoCompilationUnit)
context: g.analyzer.Context = Context(<root>#EmptyTree unit=NoCompilationUnit scope=997093283 errors=false, reportErrors=true, throwErrors=false)
// aware imports of scala._, etc.
scala> val sym = context.lookupSymbol("Option": TypeName, _ => true).symbol
sym: g.analyzer.global.Symbol = class Option
scala> sym.tpeHK.typeParams
res21: List[g.analyzer.global.Symbol] = List(type A)
See also:
scala> intp.symbolOfType("Foo")
res26: $r.intp.global.Symbol = class Foo
But I'm not sure how to get at previously imported symbols:
scala> object Bar { class Bop }
defined object Bar
scala> import Bar.Bop
import Bar.Bop
scala> intp.symbolOfType("Bop")
res27: $r.intp.global.Symbol = <none>
Edit:
The reason OP's getting ClassInfoType instead of PolyType is due to phase. To get the same result as the power mode's global, one must set the phase to typer. To quote #retronym's explanation from REPL: intp.global vs "global" available in :power mode:
scala> :power
** Power User mode enabled - BEEP WHIR GYVE **
** :phase has been set to 'typer'. **
^
`---- this part is relevant
Symbols have an list of types (aka info-s), indexed by compiler phase. (aka TypeHistory). Many compiler phases install InfoTransformers to morph the type. See src/compiler/scala/tools/nsc/transform/InfoTransform.scala for some documentation.
To inspect the type as-at particular phase, you can use methods like 'exitingTyper`.
scala> exitingPostErasure($intp.global.rootMirror.staticClass("scala.Option").typeSignature).getClass
res6: Class[_ <: $intp.global.Type] = class scala.reflect.internal.Types$ClassInfoType
scala> exitingTyper($intp.global.rootMirror.staticClass("scala.Option").typeSignature).getClass
res7: Class[_ <: $intp.global.Type] = class scala.reflect.internal.Types$PolyType
Or, a little more conveniently in :power mode:
scala> :phase typer
Active phase is now: Typer
scala> global.rootMirror.staticClass("scala.Option").typeSignature.getClass
res16: Class[_ <: $r.global.Type] = class scala.reflect.internal.Types$PolyType
scala> :phase cleanup
Active phase is now: Cleanup
scala> global.rootMirror.staticClass("scala.Option").typeSignature.getClass
res17: Class[_ <: $r.global.Type] = class scala.reflect.internal.Types$ClassInfoType
You should use the mirror from the IMain's global:
scala> val imain = new IMain()
imain: scala.tools.nsc.interpreter.IMain = scala
scala> val mirror = imain.global.rootMirror
mirror: imain.global.Mirror = compiler mirror
Is there a way to make this work? (Scala 2.8.1)
class A
def f(implicit a: A) = 0
class Vendor[T](val v: T)
implicit val vendor = new Vendor(new A)
implicit def vendorToVal[T](implicit v: Vendor[T]) = v.v
f
The error is: 'diverging implicit expansion for type A starting with method vendorToVal'
This is related to Lift 2.2 dependency injection, the real code looks like this:
class UserStore(implicit db: DbAccess)
object DependencyFactory extends Factory {
implicit val db = new FactoryMaker[DbAccess](Model) {}
import db._ // implicit conversion would allow to remove this import
implicit val userStore = new FactoryMaker[UserStore](new UserStore) {}
}
This question is related to: Is there a way to implicitly convert an implicit parameter in Scala?
The problem is caused with vendorToVal method - I observed the same behavior many times, when I've been using implicit parameters in implicit type-parametrized methods. Unfortunately, I've found no simple and elegant glue in 2.8._.
Some interesting threads, related to the topic:
http://scala-programming-language.1934581.n4.nabble.com/scala-Why-is-this-a-diverging-implicit-td1998156.html
http://www.scala-lang.org/node/6847
In Scala 2.9 trunk, you can do this:
scala> class A
defined class A
scala> def f(implicit a: A) = 0
f: (implicit a: A)Int
scala>
scala> class Vendor[T](val v: T)
defined class Vendor
scala> implicit def value[T: Vendor] = implicitly[Vendor[T]].v
value: [T](implicit evidence$1: Vendor[T])T
scala> implicit val vendor = new Vendor(new A)
vendor: Vendor[A] = Vendor#bbb2d0
scala> f
res0: Int = 0
Calling f will search for a value of type A, and find the implicit value[A], which requires an evidence parameter of type Vendor[A]. It resolves this evidence parameter to vendor.
I don't think implicits were that powerful in 2.8.1.