The following fails to compile on the last line:
// importing implicit class thru two levels
object Foo {
implicit class IntWithSquare(x: Int) {
def square = x*x
}
}
object Bar {
import Foo._
println(4.square) // this works
}
import Bar._
println(5.square) // this fails to compile
How can we force the export of imported implicit class from within Bar? The motivation for this is to keep object Foo neat by defining all implicits in a separate file. Same problem exists for other definitions coming from Foo into Bar. But, a simple re-definition of the top names works in such cases:
// importing regular definitions and types thru two levels
object Foo {
def someBigFunc(): Int = {
42
}
type Word = String
}
object Bar {
import Foo._
val someBigFunc = Foo.someBigFunc _
type Word = Foo.Word
}
import Bar._
someBigFunc()
val w: Word = "word"
The approach used to do what you want to achieve is usually to define traits and have an object extending all wanted traits.
trait Foo {
// Define implicit stuff here
}
trait Fii {
// Define other implicits here
}
object Bar extends Foo with Fii
import Bar._ // will provide the implicits from Foo and Fii
Related
I have an implicit class defined in a class injected in other classes like this
class A {
implicit class B(s: String) {
def b = ???
}
}
class C(a: A) {}
Is there a way to access implicit class B (and in particular its method b) from the class C, without importing it explicitly? (Please note that class A could not be a trait since it also injects some classes.)
Solution 1 (import a._)
Well, yes, as already noted in the comments, from your requirements it is not obvious why you wouldn't just import a._ in the body of C:
class A {
implicit class B(arg: String) {
def b: String = ???
}
}
class C(a: A) {
import a._
{
println("hello".b)
}
}
This one line really doesn't hurt anyone.
If you still don't like it, then the problem might be elsewhere. Thus my second proposal.
Solution 2 (separating typeclass-like A-interface from .b-syntax)
This other solution is less about the reduction of number of imports in your code, and it doesn't even keep class B inside A. But it might address another issue that you maybe just can't quite articulate: it separates the functionality provided by A from the syntax provided by B.
The structure of the following snippet is inspired by the design of the Scala Cats library, that follows a very clear policy with the implicit declarations, always separating the typeclass defintions from the syntax.
The main idea is that:
Implementations of AIntf provide actual functionality
B provides only some additional "pimp-my-library"-style methods
and that we want to keep these two things separate.
Here is how to separate them, thereby also avoiding import a._ inside of C. First, you define the interface that describes the functionality provided by A:
trait AIntf {
def usefulOperationOnStrings(s: String): String
}
Then you can implement it by a few different A`s:
class A extends AIntf {
def usefulOperationOnStrings(s: String): String = "<foo>" + s + "</foo>"
}
class A2 extends AIntf {
def usefulOperationOnStrings(s: String): String = s.toUpperCase
}
Note that the object B has disappeared from A. Instead, it is moved in a separate syntax-package, and renamed to A_Ops. The method b is also renamed to a:
object syntax /* should be package, object only for script */ {
object a {
class A_Ops(wrapped: String, ai: AIntf) {
def a: String = ai.usefulOperationOnStrings(wrapped)
}
implicit def everyStringHasAOps(s: String)(implicit ai: AIntf): A_Ops = {
new A_Ops(s, ai)
}
}
}
This is how you use it:
You say in the imports that you want to refer to interface A_Intf
You say in the imports that you want to use the syntax syntax.a._
You declare the a-argument of C as implicit
Then you can just use "string".a syntax inside C without further imports.
In code:
import myproject.AIntf
import myproject.syntax.a._
class C(implicit val a: AIntf) {
{
println("hello".a)
}
}
Now the implementations of AIntf and the syntax .a become independent. You can inject A2 instead of A. Or you can change the syntax from "str".a to "str".somethingEntirelyDifferent.
The full code snippet:
import scala.language.implicitConversions
object myproject /* should be package, object only for script */ {
trait AIntf {
def usefulOperationOnStrings(s: String): String
}
object syntax /* should be package, object only for script */ {
object a {
class A_Ops(wrapped: String, ai: AIntf) {
def a: String = ai.usefulOperationOnStrings(wrapped)
}
implicit def everyStringHasAOps(s: String)(implicit ai: AIntf): A_Ops = {
new A_Ops(s, ai)
}
}
}
class A extends AIntf {
def usefulOperationOnStrings(s: String): String = "<foo>" + s + "</foo>"
}
class A2 extends AIntf {
def usefulOperationOnStrings(s: String): String = s.toUpperCase
}
}
import myproject.AIntf
import myproject.syntax.a._
class C(implicit val a: AIntf) {
{
println("hello".a)
}
}
val c1 = new C()(new myproject.A)
val c2 = new C()(new myproject.A2)
// prints:
// <foo>hello</foo>
// HELLO
Unfortunately, I have no clue what guice is going to do with an implicit argument, have not tried it yet. It might force you to write
class C #Inject()(val a: AIntf) {
implicit aintf: AIntf = a
...
}
which then becomes longer then the simple import mentioned in the first part.
as noted in comment, just import a._:
class A {
implicit class B(s: String) {
def b: String = "hello "+ s
}
}
class C(a: A){
import a._
val hello = "world".b
}
val c = new C(new A)
c.hello // "hello world"
Does Scala have implicit conversions for objects? For example, if I have a method with the following signature:
object Foo {
def print(message: String) = println(message)
}
class Bar {
val baz = 1
}
How can I call Foo.print(new Bar)?
Can I put a method on the Bar class to implicitly convert Bar instance to a string without having to call toString in the argument?
C# has this and I'm wondering if scala does too.
Let's say we have Scala enum:
object Color extends Enumeration {
type Method = Value
val RED, BLUE, GREEN = Value
}
Then I have a class:
object ColorPrinter {
def print(x: String) = {
println(x)
}
}
ColorPrinter's print method can't be changed.
I want to call into ColorPrinter.print(Color.RED), but I can't do that. I would have to call it like this: ColorPrinter.print(Color.RED.toString).
I want to avoid having to toString
Converting things implicitly to basic types, like String or Int isn't really a very good idea (the implicit conversion may trigger in places where you do not expect it to, creating subtle, hard to debug, issues).
Why not just make it explicit? ?
class Bar {
val baz = 1
def print = Foo.print(toString)
}
new Bar().print
You can put implicit conversions that can be applied automatically without importing into the companion object of the class:
class Bar {
val baz = 1
}
// This should be the companion object of `Bar`, so if in console, use :paste mode
object Bar {
implicit def toString(bar: Bar): String = bar.toString
}
scala> Foo.print(new Bar) // works without `import Bar._`
$line7.$read$$iw$$iw$Bar#280ecc33
For Enumerations you can put conversions into the object itself:
object Color extends Enumeration {
type Method = Value
val RED, BLUE, GREEN = Value
implicit def toString(value: Value): String = value.toString
}
scala> ColorPrinter.print(Color.RED) // works without `import Color._`
RED
You can read more about implicit resolution in Scala in this answer: https://stackoverflow.com/a/5598107/1098230
Here is a typical approach,
yes, Implicit's very similar to C# static methods and its implemented in adhoc way:
object Foo {
def print(message: String) = println(message)
}
class Bar {
val baz = 1
}
object BarToStringMaker {
implicit def barToString(b : Bar) : String = b.baz.toString
}
import BarToStringMaker._
Foo.print(new Bar)
more reading:
http://www.artima.com/pins1ed/implicit-conversions-and-parameters.html
hope that helps,
I'm trying to provide different sets of implementations for a list of type classes, where importing different package objects would give the end user a different version of a TypeClass implementation into scope, with the swap being completely invisible.
trait TypeClass[T] {
def name: String
}
trait DefaultTypeClasses {
implicit val String: TypeClass[String]
implicit val Int: TypeClass[Int]
}
trait FirstImplementor extends DefaultTypeClasses {
implicit object String extends TypeClass[String] {
def name = "test"
}
implicit object Int extends TypeClass[Int] {
def name = "int"
}
}
object FirstImplementor extends FirstImplementor
object Test {
import FirstImplementor._
def doSomething[T : TypeClass](value: T): Unit = {
println(implicitly[TypeClass[T]].name)
}
doSomething("test")
}
The above works as expected, but if do:
trait DefaultDefinitions extends DefaultTypeClasses {
}
package object something extends DefaultDefinitions with FirstImplementor {}
And then I import the same package object into the scope of the Test object, like this:
import com.blabla.something._ // should bring all type class definitions from FirstImplementor into scope.
object Test {
def doSomething[T : TypeClass](value: T): Unit = {
println(implicitly[TypeClass[T]].name)
}
doSomething("test")// Cannot find implicit value for TypeClass[String]
doSomething[String]("test")(String) // if passed explicitly it compiles as expected, no more imports necessary.
}
For whatever reason, the materialised type class is available in explicit scope by name, but not in implicit scope. Sounds like my knowledge of the SLS is experiencing a gap, could anyone please clarify?
But if you create Implicits object in package, it works fine. However I have no idea if original error is a bug in scalac or correct behavior
package object something {
object Implicits extends DefaultDefinitions with FirstImplementor
}
import something.Implicits._
Using scala 2.10.3, my goal is to make the following work:
object A {
implicit class Imp(i: Int) {
def myPrint() {
println(i)
}
}
}
object B {
implicit class Imp(i: String) {
def myPrint() {
println(i)
}
}
}
import A._
import B._
object MyApp extends App {
3.myPrint()
}
This fails with
value myPrint is not a member of Int
If I give A.Imp and B.Imp different names (for example A.Imp1 and B.Imp2), it works.
Diving a bit deeper into it, there seems to be the same problem with implicit conversions.
This works:
object A {
implicit def Imp(i: Int) = new {
def myPrint() {
println(i)
}
}
implicit def Imp(i: String) = new {
def myPrint() {
println(i)
}
}
}
import A._
object MyApp extends App {
3.myPrint()
}
Whereas this doesn't:
object A {
implicit def Imp(i: Int) = new {
def myPrint() {
println(i)
}
}
}
object B {
implicit def Imp(i: String) = new {
def myPrint() {
println(i)
}
}
}
import A._
import B._
object MyApp extends App {
3.myPrint()
}
Why? Is this a bug in the scala compiler? I need this scenario, since my objects A and B derive from the same trait (with a type parameter) which then defines the implicit conversion for its type parameter. In this trait, I can only give one name for the implicit conversion. I want to be able to import more of these objects into my scope. Is there a way to do that?
edit: I can't give the implicit classes different names, since the examples above are only breaking down the problem. My actual code looks more like
trait P[T] {
implicit class Imp(i: T) {
def myPrint() {
...
}
}
}
object A extends P[Int]
object B extends P[String]
import A._
import B._
The implicits just have to be available as a simple name, so you can rename on import.
Just to verify:
scala> import A._ ; import B.{ Imp => BImp, _ }
import A._
import B.{Imp=>BImp, _}
scala> 3.myPrint
3
Actually, it works if you replace
import A._
import B._
with
import B._
import A._
What happens, I think, is that A.Imp is shadowed by B.Imp because it has the same name. Apparently shadowing applies on the function's name and do not take the signature into account.
So if you import A then B, then only B.Imp(i: String) will be available, and if you import B then A, then only A.Imp(i: Int) will be available.
If you need to use both A.Imp and B.Imp, you must rename one of them.
In case anyone else runs into this issue, there is a partial workaround, which I found here:
https://github.com/lihaoyi/scalatags/blob/3dea48c42c5581329e363d8c3f587c2c50d92f85/scalatags/shared/src/main/scala/scalatags/generic/Bundle.scala#L120
That code was written by Li Haoyi, so you can be pretty confident that no better solution exists...
Essentially, one can still use traits to define methods in terms of each other, but it will require boilerplate to copy those implicits into unique names. This example might be easier to follow:
trait Chainable
object Chainable {
implicit val _chainableFromInt = IntChainable.chainable _
implicit val _chainableFromIntTrav = IntChainable.traversable _
implicit val _chainableFromIntOpt = IntChainable.optional _
implicit val _chainableFromIntTry = IntChainable.tried _
implicit val _chainableFromDom = DomChainable.chainable _
implicit val _chainableFromDomTrav = DomChainable.traversable _
implicit val _chainableFromDomOpt = DomChainable.optional _
implicit val _chainableFromDomTry = DomChainable.tried _
private object IntChainable extends ImplChainables[Int] {
def chainable(n:Int) = Constant(n)
}
private object DomChainable extends ImplChainables[dom.Element]{
def chainable(e:Element) = Insertion(e)
}
private trait ImplChainables[T] {
def chainable(t:T):Chainable
def traversable(trav:TraversableOnce[T]):Chainable =
SeqChainable(trav.map(chainable).toList)
def optional(opt:Option[T]):Chainable =
opt match {
case Some(t) => chainable(t)
case None => NoneChainable
}
def tried(tried:Try[T]):Chainable =
optional(tried.toOption)
}
}
In other words, never write:
trait P[T] {
implicit def foo(i: T) = ...
}
object A extends P[X]
Because defining implicits in type parameterized traits will lead to these naming conflicts. Although, incidentally, the trait in mentioned in the link above is parameterized over many types, but idea there is that none of the implementations of that trait are ever needed in the same scope. (JSDom vs Text, and all._ vs short._ for those familiar with Scalatags)
I also recommend reading: http://www.lihaoyi.com/post/ImplicitDesignPatternsinScala.html
It does not address this issue specifically but is an excellent summary of how to use implicits.
However, putting all these pieces together, this still seems to be an issue:
trait ImplChainables[AnotherTypeClass]{
type F[A] = A=>AnotherTypeClass
implicit def transitiveImplicit[A:F](t: A):Chainable
implicit def traversable[A:F](trav: TraversableOnce[A]):Chainable = ...
}
What this trait would allow is:
object anotherImpl extends ImplChainables[AnotherTypeClass] {...}
import anotherImpl._
implicit val string2another: String=>AnotherTypeClass = ...
Seq("x"):Chainable
Because of the type parameter and the context binding (implicit parameter) those cannot be eta-expanded (i.e: Foo.bar _ ) into function values. The implicit parameter part has been fixed in Dotty: http://dotty.epfl.ch/blog/2016/12/05/implicit-function-types.html
I do not know if a complete solution would be possible, needless to say this is a complex problem. So it would be nice if same name implicits just worked and the whole issue could be avoided. And in any case, adding an unimport keyword would make so much more sense than turning off implicits by shadowing them.
Is there any way to do anything like this:
scala> trait Foo { def f:Int=0 }
defined trait Foo
scala> class FooImpl extends Foo { override val f = 1 }
defined class FooImpl
scala> class Bar(foo:Foo) extends Foo{ import foo._ }
defined class Bar
scala> (new Bar(new FooImpl)).f
res2: Int = 0
scala> trait Foo { def f:Int }
defined trait Foo
scala> class Bar(foo:Foo) extends Foo{ import foo._ }
<console>:8: error: class Bar needs to be abstract, since method f in trait Foo of type => Int is not defined
class Bar(foo:Foo) extends Foo{ import foo._ }
^
scala>
...in a way that would result in a subclass overriding a parent method via import? Basically I think it would be interesting to be able to use composition without all the typing. Just curious if anything like this is possible.
What you are really asking for is a way to delegate method implementations to a member.
That issue has already been addressed here: Proxies / delegates in Scala
Basically, there is a way to do it using macros. An implementation can be found here: https://github.com/adamw/scala-macro-aop
The above provides a #delegate macro annotation that can be applied to a data member to cause the compiler to generate code to delegate method calls to that member. Note that macro annotations are an experimental feature planned for Scala 2.11, but you can use them with Scala 2.10 using the Macro Paradise compiler plugin.
Self-typing can help here (depending on exactly how you will be working with these classes - this isn't composition of instances, more composition of types):
trait Foo { def f:Int }
trait FooImpl extends Foo { override val f = 1 } // Needs to be a trait to be mixed in.
class Bar {
this: Foo => // This requires that any Bar instance must mix in a Foo (must 'be' a Foo)
}
Then you can instantiate and use your Bar instance similar to the following:
scala> (new Bar with FooImpl).f
res1: Int = 1