Vapourise Predef.any2stringadd in interpreter - scala

I am having problem with Predef.any2stringadd that unfortunately is officially considered not a PITA. I changed my API from
trait Foo {
def +(that: Foo): Foo
}
to a type class approach
object Foo {
implicit def fooOps(f: Foo): Ops = new Ops(f)
final class Ops(f: Foo) {
def +(that: Foo): Foo = ???
}
}
trait Foo
Now I can hide that horrible method in compiled code like this:
import Predef.{any2stringadd => _}
However, this fails in my REPL/interpreter environment.
val in = new IMain(settings, out)
in.addImports("Predef.{any2stringadd => _}") // has no effect?
How can I tell the interpreter to vapourise this annoying method?

A workaround seems to be to take the implicit conversion out of Foo's companion object, and place it in the top hierarchy (package object in my real case):
object Foo {
// implicit def fooOps(f: Foo): Ops = new Ops(f)
final class Ops(f: Foo) {
def +(that: Foo): Foo = ???
}
}
trait Foo
implicit def fooOps(f: Foo): Foo.Ops = new Foo.Ops(f)
While I don't know why that should make any difference, it appears it does enough to make the interpreter forget about any2stringadd.
(Still, I think a new ticket should be opened in an attempt to remove that method, also given that string interpolation in Scala 2.10 will make it more superfluous.)

Related

Combining type bounds in Scala

Let's say I have a function such as:
def foo[T<:U <:V](t:T): Unit
I want to know if there is a way of combining these two in a type W so that I can have:
def foo[T<: W](t: T): Unit
The use case for this is:
trait FooTrait{
type W
def foo[T<: W](t: T): Unit
}
I might have two different implementations of foo, one of them with a simple W1 type bound whereas the other one is T<:W1 <:W2 I want the more complex one to define a W3 so that I can have:
def foo[T<: W3](t: T): Unit
Similiarly, I want to be able to do these with type classes. So if I have:
def bar[T<:U :V](t:T): Unit
I want to have
def bar[T:X](t:T): Unit
The use case for this is essentially the same as the earlier case.
is this possible?
In the first part of your question, the syntax isn't even valid.
If you want to impose multiple upper bounds U, V on some type T,
you have to use with keyword anyway:
trait A
trait B
def f[X <: A with B](x: X): Unit = ???
This here doesn't work:
// def f[X <: A <: B](x: X): Unit = ??? // doesn't compile
To address the second part of your question, I would like to
explain why something like with doesn't work for typeclasses.
This here does work:
trait Foo[X]
trait Bar[X]
def g[X: Foo : Bar](x: X): Unit = ???
This here doesn't work:
// def g[X: Foo with Bar](x: X): Unit = ??? // nope
Why? Because
def foo[X: Y](x: X): Ret = ???
is actually a shortcut for
def foo[X](x: X)(implicit y: Y[X]): Ret = ???
If you would try to somehow amalgamate two different typeclasses Foo and Bar,
this would result in the following desugared code:
def foo[X](x: X)(implicit superPowerfulThing: (Foo somehowGluedWith Bar)[X]): Ret = ???
But this is obviously not something that you should want.
Instead, what you want is:
def foo[X](x: X)(implicit foo: Foo[X], bar: Bar[X])(x: X): Ret = ???
In this way, the two requirements Foo and Bar can be supplied independently,
which wouldn't work if you requested some superPowerfulThing that implements
both Foo and Bar at once.
Hope that clarifies why something works or doesn't work.
Andrey Tyukin has correctly point out that with is probably the answer for your first question and that the second question has no direct solution. However if you are OK with indirect solutions, you might work this around by introducing a new type class that will says that the target types belongs to the two original type classes. Here is a simple example for imaginary typeclasses Foo and Bar and for a base trait Base with a specific implementation ChildFooBar:
trait Foo[X] {
def doFoo(x: X): String
}
trait Bar[X] {
def doBar(x: X): String
}
trait Base {
type W[_]
def baz[T: W](t: T): String
}
class ChildFooBar extends Base {
import ChildFooBar._
type W[X] = FooAndBar[X]
override def baz[T: FooAndBar](t: T): String = {
val foo = implicitly[Foo[T]]
val bar = implicitly[Bar[T]]
foo.doFoo(t) + bar.doBar(t)
}
}
object ChildFooBar {
#implicitNotFound("The type should provide both implicit Foo and implicit Bar.")
case class FooAndBar[X](foo: Foo[X], bar: Bar[X])
object FooAndBar {
implicit def fromFooAndBar[X](implicit foo: Foo[X], bar: Bar[X]): FooAndBar[X] = FooAndBar(foo, bar)
}
// private is important here to avoid diversion of implicits
private implicit def toFoo[X](implicit fooAndBar: FooAndBar[X]): Foo[X] = fooAndBar.foo
private implicit def toBar[X](implicit fooAndBar: FooAndBar[X]): Bar[X] = fooAndBar.bar
}
Now if SomeClass is a member of both Foo and Bar typeclasses, then
case class SomeClass(foo: Int, bar: Double)
object SomeClass {
implicit val foo: Foo[SomeClass] = new Foo[SomeClass] {
override def doFoo(x: SomeClass) = s"foo = ${x.foo}"
}
implicit val bar: Bar[SomeClass] = new Bar[SomeClass] {
override def doBar(x: SomeClass) = s"bar = ${x.bar}"
}
}
the simple code
println(new ChildFooBar().baz(SomeClass(1, 2.0)))
will compile and work as expected.

Scala context bounds

Using context bounds in scala you can do stuff like
trait HasBuild[T] {
def build(buildable: T): Something
}
object Builders {
implict object IntBuilder extends HasBuild[Int] {
override def build(i: Int) = ??? // Construct a Something however appropriate
}
}
import Builders._
def foo[T: HasBuild](input: T): Something = implicitly[HasBuild[T]].build(1)
val somethingFormInt = foo(1)
Or simply
val somethingFromInt = implicitly[HasBuild[Int]].build(1)
How could I express the type of a Seq of any elements that have an appropriate implicit HasBuild object in scope? Is this possible without too much magic and external libraries?
Seq[WhatTypeGoesHere] - I should be able to find the appropriate HasBuild for each element
This obviously doesn't compile:
val buildables: Seq[_: HasBuild] = ???
Basically I'd like to be able to handle unrelated types in a common way (e.g.: build), without the user wrapping them in some kind of adapter manually - and enforce by the compiler, that the types actually can be handled. Not sure if the purpose is clear.
Something you can do:
case class HasHasBuild[A](value: A)(implicit val ev: HasBuild[A])
object HasHasBuild {
implicit def removeEvidence[A](x: HasHasBuild[A]): A = x.value
implicit def addEvidence[A: HasBuild](x: A): HasHasBuild[A] = HasHasBuild(x)
}
and now (assuming you add a HasBuild[String] for demonstration):
val buildables: Seq[HasHasBuild[_]] = Seq(1, "a")
compiles, but
val buildables1: Seq[HasHasBuild[_]] = Seq(1, "a", 1.0)
doesn't. You can use methods with implicit HasBuild parameters when you have only a HasHasBuild:
def foo1[A](x: HasHasBuild[A]) = {
import x.ev // now you have an implicit HasBuild[A] in scope
foo(x.value)
}
val somethings: Seq[Something] = buildables.map(foo1(_))
First things first, contrary to some of the comments, you are relying on context bounds. Requesting an implicit type class instance for a T is what you call a "context bound".
What you want is achievable, but not trivial and certainly not without other libraries.
import shapeless.ops.hlist.ToList
import shapeless._
import shapeless.poly_
object builder extends Poly1 {
implicit def caseGeneric[T : HasBuilder] = {
at[T](obj => implicitly[HasBuilder[T]].build(obj))
}
}
class Builder[L <: HList](mappings: L) {
def build[HL <: HList]()(
implicit fn: Mapper.Aux[builder.type, L, HL],
lister: ToList[Something]
) = lister(mappings map fn)
def and[T : HasBuilder](el: T) = new Builder[T :: L](el :: mappings)
}
object Builder {
def apply[T : HasBuilder](el: T) = new Builder(el :: HNil)
}
Now you might be able to do stuff like:
Builder(5).and("string").build()
This will call out the build methods from all the individual implcit type class instances and give you a list of the results, where every result has type Something. It relies on the fact that all the build methods have a lower upper bound of Something, e.g as per your example:
trait HasBuild[T] {
def build(buildable: T): Something
}

A case class as a "wrapper" class for a collection. What about map/foldLeft/

What I try to do is to come up with a case class which I can use in pattern matching which has exactly one field, e.g. an immutable set. Furthermore, I would like to make use of functions like map, foldLeft and so on which should be passed down to the set. I tried it as in the following:
case class foo(s:Set[String]) extends Iterable[String] {
override def iterator = s.iterator
}
Now if I try to make use of e.g. the map function, I get an type error:
var bar = foo(Set() + "test1" + "test2")
bar = bar.map(x => x)
found : Iterable[String]
required: foo
bar = bar.map(x => x)
^
The type error is perfectly fine (in my understanding). However, I wonder how one would implement a wrapper case class for a collection such that one can call map, foldLeft and so on and still receive an object of the case class. Would one need to override all these functions or is there some other way around?
Edit
I'm inclined to accept the solution of RĂ©gis Jean-Gilles which works for me. However, after Googling for hours I found another interesting Scala trait named SetProxy. I couldn't find any trivial examples so I'm not sure if this trait does what I want:
come up with a custom type, i.e. a different type than Set
the type must be a case class (we want to do pattern matching)
we need "delegate" methods map, foldLeft and so on which should pass the call to our actual set and return the resulting set wrapped arround in our new type
My first idea was to extend Set but my custom type Foo already extends another class. Therefore, the second idea was to mixin the trait Iterable and IterableLike. Now I red about the trait SetProxy which made me think about which is "the best" way to go. What are your thoughts and experiences?
Since I started learning Scala three days ago, any pointers are highly appreciated!
Hmm this sounds promissing to me but Scala says that variable b is of type Iterable[String] and not of type Foo, i.e. I do not see how IterableLike helps in this situation
You are right. Merely inheriting from IterableLike as shown by mpartel will make the return type of some methods more precise (such as filter, which will return Foo), but for others such as map of flatMap you will need to provide an appopriate CanBuildFrom implicit.
Here is a code snippet that does just that:
import collection.IterableLike
import collection.generic.CanBuildFrom
import collection.mutable.Builder
case class Foo( s:Set[String] ) extends Iterable[String] with IterableLike[String, Foo] {
override def iterator = s.iterator
override protected[this] def newBuilder: scala.collection.mutable.Builder[String, Foo] = new Foo.FooBuilder
def +(elem: String ): Foo = new Foo( s + elem )
}
object Foo {
val empty: Foo = Foo( Set.empty[String] )
def apply( elems: String* ) = new Foo( elems.toSet )
class FooBuilder extends Builder[String, Foo] {
protected var elems: Foo = empty
def +=(x: String): this.type = { elems = elems + x; this }
def clear() { elems = empty }
def result: Foo = elems
}
implicit def canBuildFrom[T]: CanBuildFrom[Foo, String, Foo] = new CanBuildFrom[Foo, String, Foo] {
def apply(from: Foo) = apply()
def apply() = new FooBuilder
}
}
And some test in the repl:
scala> var bar = Foo(Set() + "test1" + "test2")
bar: Foo = (test1, test2)
scala> bar = bar.map(x => x) // compiles just fine because map now returns Foo
bar: Foo = (test1, test2)
Inheriting IterableLike[String, Foo] gives you all those methods such that they return Foo. IterableLike requires you to implement newBuilder in addition to iterator.
import scala.collection.IterableLike
import scala.collection.mutable.{Builder, SetBuilder}
case class Foo(stuff: Set[String]) extends Iterable[String] with IterableLike[String, Foo] {
def iterator: Iterator[String] = stuff.iterator
protected[this] override def newBuilder: Builder[String, Foo] = {
new SetBuilder[String, Set[String]](Set.empty).mapResult(Foo(_))
}
}
// Test:
val a = Foo(Set("a", "b", "c"))
val b = a.map(_.toUpperCase)
println(b.toList.sorted.mkString(", ")) // Prints A, B, C

Type aliases screw up type tags?

Why don't type tags work with type aliases. E.g. given
trait Foo
object Bar {
def apply[A](implicit tpe: reflect.runtime.universe.TypeTag[A]): Bar[A] = ???
}
trait Bar[A]
I would like to use an alias within the following method, because I need to type A around two dozen times:
def test {
type A = Foo
implicit val fooTpe = reflect.runtime.universe.typeOf[A] // no funciona
Bar[A] // no funciona
}
Next try:
def test {
type A = Foo
implicit val fooTpe = reflect.runtime.universe.typeOf[Foo] // ok
Bar[A] // no funciona
}
So it seems I can't be using my alias at all.
Use weakTypeOf instead. Reflection internally distinguishes globally visible and local declarations, so you need to treat them differently as well. This wart may be removed in later versions of Scala.
Change def apply declaration:
import scala.reflect.runtime.universe._
trait Foo
object Bar {
def apply[A]()(implicit tpe: TypeTag[A]): Bar[A] = ???
}
trait Bar[A]
class test {
type A = Foo
implicit val foo = typeOf[A]
def test = Bar[A]()
}

Implicit parameter resolution for higher kinded types

Consider the following code:
object foo {
trait Bar[Q[_]]
implicit object OptionBar extends Bar[Option]
def test[T, C[_]](c: C[T])(implicit bar: Bar[C]) = ()
def main(args: Array[String]) {
test(Some(42): Option[Int]) //???
}
}
This works, but I need to type the Some(42) as Option[Int], else the implicit object OptionBar won't be resolved (because a Bar[Some] is expected instead). Is there a way to avoid the explicit typing, so that I get the implicit OptionBar object in test even if I feed test with a Some or None?
[Clarification]
I used Option here just as example, it should also work if I have a Bar for an abstract class etc.
The solution should also work when other, unrelated Bars are in scope, say implicit object listBar extends Bar[list]
[Update]
It seems that making Bar's parameter contravariant does the trick:
object foo {
trait Bar[-Q[_]] //<---------------
implicit object OptionBar extends Bar[Option]
implicit object ListBar extends Bar[List]
def test[T, C[_]](c: C[T])(implicit bar: Bar[C]) = ()
def main(args:Array[String]) {
test(Some(42))
}
}
But of course this is a severe limitation of the possibilities in Bar, so I still hope for a better answer.
It's not going to work in all cases, but as stated, you can try this:
object foo {
trait Bar[Q[_]]
implicit object OptionBar extends Bar[Option]
def test[T, C[_], D](c: D)(implicit bar: Bar[C], ev: D <:< C[T]) = ()
def main(args: Array[String]) {
test(Some(42)) //???
}
}
Interestingly, this doesn't infer, although it expresses the same thing:
def test[T, C[_], D <: C[T]](c: D)(implicit bar: Bar[C]) = ()
To learn more about <:<, see:
What do <:<, <%<, and =:= mean in Scala 2.8, and where are they documented?
<:< operator in scala
That's because Some(42) is a more specific type than Option[Int]. It is a Some[Int]. See alternative coding below:
object foo {
trait Bar[Q[_]]
implicit object OptionBar extends Bar[Option]
def test[T, C[_]](c: C[T])(implicit bar: Bar[C]) = ()
def main(args: Array[String]) {
test(Option(42))
}
}