In Scala, what's the most generalizable way to require a type can be treated as a String?
I know view bound requires that an object can be "viewed as" another type, but this doesn't work.
def func[T <% String](s: T): String = s.toString
val x: Long = 0
x.toString // String = 0
func(x) // error: No implicit view available from Long => String.
Type Any has a toString method... so I could just do a type bound... but is every object in Scala automatically a subtype of Any? It seems like maybe, but is this dumb for some reason I'm not anticipating?
def func[T <: Any](s: T): String = s.toString
class A { override def toString "xxx" }
func(new A) // String = xxx
class B(val b: Int)
func(new B(0)) // String = B#12345678
object C { override def toString = "ccc" }
func(C) // String = ccc
So it seems to work, even though my objects don't explicitly extend any subclass of Any. Will this generalize to any object in Scala, even if it doesn't necessarily end up with a pretty string that looks like what I want?
EDIT
per comment below, viewing as a string and creating a new string are different. in this case, I don't care, but to make the view bound version work... I'd guess something like this would be appropriate?
implicit def strConv[T](s: T) = s.toString
def func[T <% String](s: T) = s
func(new A) // A = xxx
Regarding your edit and what those view bounds are for.
A view bound exists to allow you to have a function that will accept any type so long as an implicit conversion exists to the type you wish you had. I'm going to make your sample function just a touch fancier in the interests of showing what that really means.
First, some implicit conversions (I'm going to stick with Long and Double to drive the point home)
implicit def long2String(l: Long) = l.toString
implicit def double2String(d: Double) = d.toString
Now, a function that really wants to operate on Strings, but will accept anything that's convertible to String
def func[T <% String](s: T) = s.substring(0,2)
Now, if I call that function with a Double, I'll get this
scala> func(9.123)
res8: String = 9.
And with a Long
scala> func(999999L)
res7: String = 99
But with an Int
scala> func(99)
<console>:15: error: No implicit view available from Int => String.
func(99)
Your specific example
def func[T <% String](s: T) = s
doesn't quite work, though, since it actually returns T not String. You can do this, though.
def func[T <% String](s: T): String = s
Yeah it will always work: Any is the highest thing in the hierarchy. Check out the diagram. Looks like it generalizes Scala's value types (AnyVal) and reference types (AnyRef). As a consequence, T <: Any will be true for any T.
With that in mind, you can drop T <: Any completely (and replace it with just T). Heck, the REPL even simplifies it for you:
scala> def func[T <: Any](s: T): String = s.toString
func: [T](s: T)String
EDIT
In case it isn't clear - you might as well just use .toString straight up - this function will serve no purpose.
Related
I have a piece of code in implicit class -
implicit class Path(bSONValue: BSONValue) {
def |<[S, T <:{def value:S}] = {
bSONValue.asInstanceOf[T].value
}
}
The problem is if I want to call |< method after BSONValue I need to call with . .
e.g
(doc/"_id").|<[String,BSONString]
The problem is without . scala raises error because it does not allow type parameter method with infix notation. So always I have to wrap doc/"_id" portion with ().
Is their any way of using type parameter method without . eg
doc/"_id"|<[String,BSONString]
All types T that you want to get out of BSONValues will probably have a companion object with the same name. You could use that companion object as an intuitive placeholder for the type that you actually want to get. Something along these lines:
trait Extract[A, BComp, B] {
def extractValue(a: A): B
}
implicit class Extractable[A](a: A) {
def |<[BC, B]
(companion: BC)
(implicit e: Extract[A, BC, B])
: B = e.extractValue(a)
}
implicit def extractIntFromString
: Extract[String, Int.type, Int] = _.toInt
implicit def extractDoubleFromString
: Extract[String, Double.type, Double] = _.toDouble
val answer = "42" |< Int
val bnswer = "42.1" |< Double
This allows you to use infix syntax, because all those things are ordinary values.
Still, only because it's possible, it doesn't mean that you have to do it.
For instance, I wouldn't know what to expect from a |<-operator.
Many other people also wouldn't know what to do with it.
They'd have to go and look it up. Then they would see this signature:
def |<[BC, B](companion: BC)(implicit e: Extract[A, BC, B]): B
I can imagine that the vast majority of people (myself in one week included) would not be immediately enlightened by this signature.
Maybe you could consider something more lightweight:
type BSONValue = String
trait Extract[B] {
def extractValue(bsonValue: BSONValue): B
}
def extract[B](bson: BSONValue)(implicit efb: Extract[B])
: B = efb.extractValue(bson)
implicit def extractIntFromString
: Extract[Int] = _.toInt
implicit def extractDoubleFromString
: Extract[Double] = _.toDouble
val answer = extract[Int]("42")
val bnswer = extract[Double]("42.1")
println(answer)
println(bnswer)
It seems to do roughly the same as the |< operator, but with much less magic going on.
Suppose you have a trait like this:
trait Foo[A]{
def foo: A
}
I want to create a function like this:
def getFoo[A <: Foo[_]](a: A) = a.foo
The Scala Compiler deduces Any for the return type of this function.
How can I reference the anonymous parameter _ in the signature (or body) of getFoo?
In other words, how can I un-anonymize the parameter?
I want to be able to use the function like
object ConcreteFoo extends Foo[String] {
override def foo: String = "hello"
}
val x : String = getFoo(ConcreteFoo)
which fails compilation for obvious reasons, because getFoo is implicitly declared as Any.
If this is not possible with Scala (2.12 for that matter), I'd be interested in the rational or the technical reason for this limitation.
I am sure there are articles and existing questions about this, but I appear to be lacking the correct search terms.
Update: The existing answer accurately answers my question as stated, but I suppose I wasn't accurate enough regarding my actual usecase. Sorry for the confusion. I want to be able to write
def getFoo[A <: Foo[_]] = (a: A) => a.foo
val f = getFoo[ConcreteFoo.type]
//In some other, unrelated place
val x = f(ConcreteFoo)
Because I don't have a parameter of type A, the compiler can't deduce the parameters R and A if I do
def getFoo[R, A <: Foo[R]]: (A => R) = (a: A) => a.foo
like suggested. I would like to avoid manually having to supply the type parameter R (String in this case), because it feels redundant.
To answer literally your exact question:
def getFoo[R, A <: Foo[R]](a: A): R = a.foo
But since you don't make any use of the type A, you can actually omit it and the <: Foo[..] bound completely, retaining only the return type:
def getFoo[R](a: Foo[R]): R = a.foo
Update (the question has been changed quite significantly)
You could smuggle in an additional apply invocation that infers the return type from a separate implicit return type witness:
trait Foo[A] { def foo: A }
/** This is the thing that remembers the actual return type of `foo`
* for a given `A <: Foo[R]`.
*/
trait RetWitness[A, R] extends (A => R)
/** This is just syntactic sugar to hide an additional `apply[R]()`
* invocation that infers the actual return type `R`, so you don't
* have to type it in manually.
*/
class RetWitnessConstructor[A] {
def apply[R]()(implicit w: RetWitness[A, R]): A => R = w
}
def getFoo[A <: Foo[_]] = new RetWitnessConstructor[A]
Now it looks almost like what you wanted, but you have to provide the implicit, and you have to call getFoo[ConcreteFoo.type]() with additional pair of round parens:
object ConcreteFoo extends Foo[String] {
override def foo: String = "hey"
}
implicit val cfrw = new RetWitness[ConcreteFoo.type, String] {
def apply(c: ConcreteFoo.type): String = c.foo
}
val f = getFoo[ConcreteFoo.type]()
val x: String = f(ConcreteFoo)
I'm not sure whether it's really worth it, it's not necessarily the most straightforward thing to do. Type-level computations with implicits, hidden behind somewhat subtle syntactic sugar: that might be too much magic hidden behind those two parens (). Unless you expect that the return type of foo will change very often, it might be easier to just add a second generic argument to getFoo, and write out the return type explicitly.
I've been experimenting with implicit conversions, and I have a decent understanding of the 'enrich-my-libray' pattern that uses these. I tried to combine my understanding of basic implicits with the use of implicit evidence... But I'm misunderstanding something crucial, as shown by the method below:
import scala.language.implicitConversions
object Moo extends App {
case class FooInt(i: Int)
implicit def cvtInt(i: Int) : FooInt = FooInt(i)
implicit def cvtFoo(f: FooInt) : Int = f.i
class Pair[T, S](var first: T, var second: S) {
def swap(implicit ev: T =:= S, ev2: S =:= T) {
val temp = first
first = second
second = temp
}
def dump() = {
println("first is " + first)
println("second is " + second)
}
}
val x = new Pair(FooInt(200), 100)
x.dump
x.swap
x.dump
}
When I run the above method I get this error:
Error:(31, 5) Cannot prove that nodescala.Moo.FooInt =:= Int.
x.swap
^
I am puzzled because I would have thought that my in-scope implict conversion would be sufficient 'evidence' that Int's can be converted to FooInt's and vice versa. Thanks in advance for setting me straight on this !
UPDATE:
After being unconfused by Peter's excellent answer, below, the light bulb went on for me one good reason you would want to use implicit evidence in your API. I detail that in my own answer to this question (also below).
=:= checks if the two types are equal and FooInt and Int are definitely not equal, although there exist implicit conversion for values of these two types.
I would create a CanConvert type class which can convert an A into a B :
trait CanConvert[A, B] {
def convert(a: A): B
}
We can create type class instances to transform Int into FooInt and vise versa :
implicit val Int2FooInt = new CanConvert[Int, FooInt] {
def convert(i: Int) = FooInt(i)
}
implicit val FooInt2Int = new CanConvert[FooInt, Int] {
def convert(f: FooInt) = f.i
}
Now we can use CanConvert in our Pair.swap function :
class Pair[A, B](var a: A, var b: B) {
def swap(implicit a2b: CanConvert[A, B], b2a: CanConvert[B, A]) {
val temp = a
a = b2a.convert(b)
b = a2b.convert(temp)
}
override def toString = s"($a, $b)"
def dump(): Unit = println(this)
}
Which we can use as :
scala> val x = new Pair(FooInt(200), 100)
x: Pair[FooInt,Int] = (FooInt(200), 100)
scala> x.swap
scala> x.dump
(FooInt(100), 200)
A =:= B is not evidence that A can be converted to B. It is evidence that A can be cast to B. And you have no implicit evidence anywhere that Int can be cast to FooInt vice versa (for good reason ;).
What you are looking for is:
def swap(implicit ev: T => S, ev2: S => T) {
After working through this excercise I think I have a better understanding of WHY you'd want to use implicit evidence serves in your API.
Implicit evidence can be very useful when:
you have a type parameterized class that provides various methods
that act on the types given by the parameters, and
when one or more of those methods only make sense when additional
constraints are placed on parameterized types.
So, in the case of the simple API given in my original question:
class Pair[T, S](var first: T, var second: S) {
def swap(implicit ev: T =:= S, ev2: S =:= T) = ???
def dump() = ???
}
We have a type Pair, which keeps two things together, and we can always call dump() to examine the two things. We can also, under certain conditions, swap the positions of the first and second items in the pair. And those conditions are given by the implicit evidence constraints.
The Programming in Scala book gives a nice example of how this technique
is used in Scala collections, specifically on the toMap method of Traversables.
The book points out that Map's constructor
wants key-value pairs, i.e., two-tuples, as arguments. If we have a
sequence [Traversable] of pairs, wouldn’t it be nice to create a Map
out of them in one step? That’s what toMap does, but we have a
dilemma. We can’t allow the user to call toMap if the sequence is not
a sequence of pairs.
So there's an example of a type [Traversable] that has a method [toMap] that can't be used in all situations... It can only be used when the compiler can 'prove' (via implicit evidence) that the items in the Traversable are pairs.
How would one encode the following constraint in Scala (pseudocode)?
def foo(x: T forSome { type T has a Numeric[T] instance in scope }) = {
val n= implicitly[...] // obtain the Numeric instance for x
n.negate(x) // and use it with x
}
In words: I need a type class instance for my input argument, but I don't care about the argument's type, I just need to obtain the instance and use it on my argument.
It doesn't have to be an existential type, but I need to avoid type parameters in the def's signature.
Edit: just to clarify, the standard approach in these cases, i.e.:
def foo[T: Numeric](x: T) = ...
doesn't work for me, as it requires the addition of a type parameter on the method.
Thanks.
I managed to make it work like this:
implicit class InstanceWithNumeric[T](val inst: T)(implicit val n: Numeric[T])
def foo(iwn: InstanceWithNumeric[_]) {
def genFoo[T](iwn: InstanceWithNumeric[T]) {
println(iwn.n.negate(iwn.inst))
}
genFoo(iwn)
}
And now:
scala> foo(1)
-1
scala> foo(1.2)
-1.2
Not the prettiest, but seems to work.
EDIT: You can avoid defining inner function like this:
implicit class InstanceWithNumeric[T](val inst: T)(implicit val n: Numeric[T]) {
def negate = n.negate(inst)
}
Also, if you want to make implicit conversion to InstanceWithNumeric globally visible, you can do something like this:
class InstanceWithNumeric[T](val inst: T)(implicit val n: Numeric[T])
object InstanceWithNumeric {
implicit def apply[T: Numeric](inst: T) =
new InstanceWithNumeric(inst)
}
If you want to understand how this works, read about so called implicit scope (this question seems to contain good explanation).
Not quite sure what you are attempting, because it seems you need a type once you make the call to implicitly. Would the following work for you?
def foo(implicit x: Numeric[_]) {
//code goes here.
}
Given a polymorphic trait like
trait Transform[T] { def apply( t: T ) : T }
one might like to implement various specialized instances, such as
case class Add[Double] extends Transform[Double] { def apply( t: Double ) ... }
case class Append[String] extends Transform[String] { def apply( t: String ) ... }
etc. Now a frequently desired transform is also the identity transform. Instead of specializing identity for each type T, it appears preferable to use just one singleton instance for all types T. My question is: what is the best way to accomplish this in Scala?
Here is what I found so far: looking at how List[T] implements List.empty[T] and Nil, I tried using Nothing as the type T. This seems to make sense, since Nothing is a subtype of every other type:
object Identity extends Transform[Nothing] {
def apply( t: Nothing ) = t
}
This seems to work. However, wherever I then want use this instance as-is, like here:
val array = Array[Transform[String]]( Transform.Identity )
I get the compiler error "type mismatch; found: Identity.type, required: Transform[String]". In order to use it, I have to explicitly cast it:
... Identity.asInstanceOf[Transform[String]]
I am not sure this is the best or even the 'proper' way to do it. Thanks for any advice.
As #Kim Stebel points out your Transform[T] is invariant in T (and has to be because T occurs in both co- and contra- variant positions in def apply(t : T) : T) so Transform[Nothing] is not a subtype of Transform[String] and can't be made to be.
If your main concern is the instance creation on each call of Kim's def Id[A] then your best model is the definition of conforms in in Predef,
private[this] final val singleton_<:< = new <:<[Any,Any] { def apply(x: Any): Any = x }
implicit def conforms[A]: A <:< A = singleton_<:<.asInstanceOf[A <:< A]
ie. use a polymorphic method, returning a singleton value cast to the appropriate type. This is one of occasions where erasure is a win.
Applied to your situation we would have,
object SingletonId extends Transform[Any] { def apply(t : Any) = t }
def Id[A] = SingletonId.asInstanceOf[Transform[A]]
Sample REPL session,
scala> Id("foo")
res0: java.lang.String = foo
scala> Id(23)
res1: Int = 23
Since the type parameter T in Transform[T] is invariant, Transform[Nothing] is not a subtype of Transform[String], thus the compiler complains about it. But using Nothing here doesn't make sense anyway, since there can never be an instance of Nothing. So how would you pass one to the apply method? You would need to cast yet again. The only option I can see is this:
scala> def Id[A] = new Transform[A] { override def apply(t:A) = t }
Id: [A]=> java.lang.Object with Transform[A]
scala> Id(4)
res0: Int = 4
scala> Id("")
res1: java.lang.String = ""