I know this can be done but I can't remember (or locate) the syntax for the life of me. How can I specify that a specific function must be present on a generic type in a function definition?
For instance, I know I can do this:
def blah[A](p: A)
What I really want is something like this (but my syntax is all wrong of course):
def blah[A(someFunction)](p: A)
I am not sure if using this is a good idea, but here is how it works:
def blah[A <: { def someFunction: String }](a: A) : Unit =
println(a.someFunction)
scala> class Test { def someFunction: String = "hello" }
defined class Test
scala> blah(new Test)
hello
scala> class Test2
defined class Test2
scala> blah(new Test2)
<console>:16: error: inferred type arguments [Test2] do not conform to method blah's type parameter bounds [A <: AnyRef{def someFunction: String}]
Note that this feature (so-called structural types) uses reflection, and has to be enabled using the language import import scala.language.reflectiveCalls
What you're looking for is called a "structural type".
Any example from here: https://twitter.github.io/scala_school/advanced-types.html
scala> def foo(x: { def get: Int }) = 123 + x.get
foo: (x: AnyRef{def get: Int})Int
scala> foo(new { def get = 10 })
res0: Int = 133
Note, however, that this is going to be slower than just declaring a trait that requiring that any argument implements that trait.
Related
Given a made-up F type-class:
scala> trait F[A] {}
defined trait F
and this definition, which uses a context bound to require that the input A has a type-class instance of F:
scala> def f[A : F](x: A) = ???
f: [A](x: A)(implicit evidence$1: F[A])Nothing
I defined a Person and type-class instance:
scala> case class Person(name: String)
defined class Person
scala> implicit val person: F[Person] = new F[Person] {}
person: F[Person] = $anon$1#262b2c86
And the following compiles:
scala> f(Person("foo"))
scala.NotImplementedError: an implementation is missing
But, there's no String implementation, so it fails.
scala> f("foobar")
<console>:17: error: could not find implicit value for evidence parameter of type F[String]
f("foobar")
^
I then defined an F[String] using:
scala> implicit def fInstance(x: String) = new F[String] {}
fInstance: (x: String)F[String]
But, I can't run:
scala> f("foobar")
<console>:18: error: could not find implicit value for evidence parameter of type F[String]
f("foobar")
^
since I do not have an implicit F[String], but rather a String => F[String].
What's the proper way to use such an implicit def to meet the F[String] constraint, i.e. call the f function successfully with a type of String?
I got it to work via:
scala> implicit val x: F[String] = implicitly[String => F[String]].apply("foobar")
x: F[String] = $anon$1#7b7fdc8
scala> f("foobar")
scala.NotImplementedError: an implementation is missing
at scala.Predef$.$qmark$qmark$qmark(Predef.scala:230)
at .f(<console>:12)
... 33 elided
But I'm not sure if it's the right/clean way to do it.
You defined an implicit conversion. If you want to use a def to provide typeclass instances you just write the same as you'd write an implicit val but replace val with def.
implicit def fInstance = new F[String] {}
Normally you only use a def if you need type parameters, like here.
implicit def fInstance[A] = new F[List[A]] {}
Or
implicit def fInstance[A](implicit ev: F[A]) = new F[List[A]] {}
Your fInstance defines an implicit conversion, i.e. a way to turn a String into F[String]. For generating a typeclass instance, a method accepting implicit parameters can be used:
implicit def fInstance(implicit x: String) = new F[String] {}
it is typically used in FP libraries to derive one typeclass from another:
implicit def optionMonoid[A](implicit S: Semigroup[A]): Monoid[Option[A]] = ???
// or, which is the same
// implicit def optionMonoid[A: Semigroup]: Monoid[Option[A]] = ???
The idea is that F[String] can operate on any String in general, not being dependent on actual arguments provided into function. Of course, you can always provide instances explicitly:
f("foobar")(new F[String] { })
As a follow-up, the important part of typeclasses is that you can define them ad-hoc, i.e. not having access to definitions of F and String at all, and you are forced to scope implicits in Scala and import them, so it's totally ok.
Here is a simpler version of your definition (and you can remove implicit from fInstance):
implicit val singleFInstance: F[String] = fInstance("") // or fInstance("foobar"), etc.
Whether this is the right thing to do, very much depends on what F and f are supposed to mean.
But generally speaking: if F is really a type-class, fInstance(string) gives different results depending on the string (not just different instances, but different behavior), and f's signature is correct, then this is wrong and you should accept that calling f("foobar") isn't meaningful.
Given:
scala> trait Resource[A] { def f: String }
defined trait Resource
scala> case class Foo(x: String)
defined class Foo
And then an implicit:
scala> implicit def fooToResource(foo: Foo): Resource[Foo] =
new Resource[Foo] { def f = foo.x }
The following works:
scala> implicitly[Resource[Foo]](Foo("foo")).f
res2: String = foo
I defined a function:
scala> def f[A](x: A)(implicit ev: Resource[A]): String = ev.f
f: [A](x: A)(implicit ev: Resource[A])String
However, the following code fails to compile:
scala> f(Foo("foo"))
<console>:17: error: could not find implicit value for parameter ev: Resource[Foo]
f(Foo("foo"))
Secondly, then I tried:
scala> f2(Foo("bippy"))
<console>:17: error: could not find implicit value for parameter ev: Resource[Foo]
f2(Foo("bippy"))
^
Lastly, I attempted:
scala> def g(foo: Foo)(implicit ev: Resource[Foo]): String = ev.f
g: (foo: Foo)(implicit ev: Resource[Foo])String
scala> g(Foo("5"))
<console>:17: error: could not find implicit value for parameter ev: Resource[Foo]
g(Foo("5"))
^
However, it failed too. How can I fix f?
Ok with Peter Neyens' answer, this is not a typeclass, this is an implicit conversion, which you should avoid - there should have been some warning, asking that you import scala.language.implicitConversions.
As a complement, here is why the first implicitly works:
Implicitly is just:
def implicitly[T](implicit ev: T): T = e
When you write implicitly[T] without supplying a parameter, it will look for an implicit of type T in scope and return it. However, you call implicitly with a parameter (I believe there is no legitimate reason to do that, ever), so it would just return your parameter, Foo("foo"), an instance of Foo. Except that you explicitly stated that T should be Resource[Foo]. If you had written a type ascription, such as (Foo("foo"): Resource[Foo]), it would have worked the same way. implicitly is not relevant here.
The point is that Foo("foo") is not of the expected type Resource[Foo], but just a Foo. The compiler would reject that, except that at this point, the implicit conversion you defined above kicks in, and your Foo instance is transformed into a Resource[Foo]. Then, you can call f.
Next, you call your f(Foo("foo")). There is an implicit parameter, however this time, you don't supply it. So the compiler looks for one (while it did no such thing the first time), and as there is no such instance, fails.
The implicit def fooToResource is not a type class instance, but does return one if you supply a Foo, that's the reason the following line works :
implicitly[Resource[Foo]](Foo("foo")).f
A solution would be to change the Resource.f function to take a parameter of type A :
trait Resource[A] {
def f(a: A): String
}
You then could define a Resource type class instance for Foo as follows:
case class Foo(x: String)
implicit val fooResource = new Resource[Foo] {
def f(foo: Foo) = foo.x
}
We can rewrite f to use the changed Resource :
def f[A](a: A)(implicit resA: Resource[A]): String = resA.f(a)
Which does what (I think) you need :
f(Foo("hello world")) // String = hello world
While dealing with some Java code, I wanted to find a way to reduce a Raw Set to include its parameterized type.
I also wanted it to work for Scala sets as well, so I did the following
implicit class Harden[S <% mutable.Set[_]](val set: S) extends AnyVal {
def cast[T] = set.map(_.asInstanceOf[T])
}
That resulted in a compiler error that I didn't expect
Error:(27, 27) field definition is not allowed in value class
implicit class Harden[S <% mutable.Set[_]](val set: S) extends AnyVal {
I didn't find any mention of this type of restriction in the Scala View Bounds or Value Class documentation.
Why is this not allowed? I'm using Scala 2.10.3.
As you can see from this sbt console output:
scala> :type implicit class Harden[S <% mutable.Set[_]](val set: S)
[S]AnyRef {
val set: S
private[this] val set: S
implicit private[this] val evidence$1: S => scala.collection.mutable.Set[_]
def <init>(set: S)(implicit evidence$1: S => scala.collection.mutable.Set[_]): Harden[S]
}
... the actual constructor of Harden desugars behind the scenes to:
def <init>(set: S)(implicit evidence$1: S => scala.collection.mutable.Set[_]): Harden[S]
... (i.e. takes set in one argument list and implicit evidence$1 in another).
As described in value classes limitations here:
must have only a primary constructor with exactly one public, val parameter whose type is not a value class.
... whitch means that Harden violaties this limitation.
You can achieve something similar, howerver. Try to convert your view bound defined on class to implicit evidence on method instead.
Something like this:
scala> implicit class Harden[S](val set: S) extends AnyVal {
| def cast[T](implicit ev: S => scala.collection.mutable.Set[_]) = set.map(_.asInstanceOf[T])
| }
defined class Harden
This will compile:
scala> Set(1,2,3).cast[Any]
res17: scala.collection.mutable.Set[Any] = Set(1, 2, 3)
And this will fail, as expected:
scala> List(1,2,3).cast[Any]
<console>:24: error: No implicit view available from List[Int] => scala.collection.mutable.Set[_].
List(1,2,3).cast[Any]
^
It is not allowed because as structured now, value classes must have exactly one parameter, but
implicit class Foo[A <% B](val a: A)
desugars to
implicit class Foo[A,B](val a: A)(implicit evidence$1: A => B)
which no longer has just a single parameter.
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 = ""
I wrote this in scala and it won't compile:
class TestDoubleDef{
def foo(p:List[String]) = {}
def foo(p:List[Int]) = {}
}
the compiler notify:
[error] double definition:
[error] method foo:(List[String])Unit and
[error] method foo:(List[Int])Unit at line 120
[error] have same type after erasure: (List)Unit
I know JVM has no native support for generics so I understand this error.
I could write wrappers for List[String] and List[Int] but I'm lazy :)
I'm doubtful but, is there another way expressing List[String] is not the same type than List[Int]?
Thanks.
I like Michael Krämer's idea to use implicits, but I think it can be applied more directly:
case class IntList(list: List[Int])
case class StringList(list: List[String])
implicit def il(list: List[Int]) = IntList(list)
implicit def sl(list: List[String]) = StringList(list)
def foo(i: IntList) { println("Int: " + i.list)}
def foo(s: StringList) { println("String: " + s.list)}
I think this is quite readable and straightforward.
[Update]
There is another easy way which seems to work:
def foo(p: List[String]) { println("Strings") }
def foo[X: ClassTag](p: List[Int]) { println("Ints") }
def foo[X: ClassTag, Y: ClassTag](p: List[Double]) { println("Doubles") }
For every version you need an additional type parameter, so this doesn't scale, but I think for three or four versions it's fine.
[Update 2]
For exactly two methods I found another nice trick:
def foo(list: => List[Int]) = { println("Int-List " + list)}
def foo(list: List[String]) = { println("String-List " + list)}
Instead of inventing dummy implicit values, you can use the DummyImplicit defined in Predef which seems to be made exactly for that:
class TestMultipleDef {
def foo(p:List[String]) = ()
def foo(p:List[Int])(implicit d: DummyImplicit) = ()
def foo(p:List[java.util.Date])(implicit d1: DummyImplicit, d2: DummyImplicit) = ()
}
To understand Michael Krämer's solution, it's necessary to recognize that the types of the implicit parameters are unimportant. What is important is that their types are distinct.
The following code works in the same way:
class TestDoubleDef {
object dummy1 { implicit val dummy: dummy1.type = this }
object dummy2 { implicit val dummy: dummy2.type = this }
def foo(p:List[String])(implicit d: dummy1.type) = {}
def foo(p:List[Int])(implicit d: dummy2.type) = {}
}
object App extends Application {
val a = new TestDoubleDef()
a.foo(1::2::Nil)
a.foo("a"::"b"::Nil)
}
At the bytecode level, both foo methods become two-argument methods since JVM bytecode knows nothing of implicit parameters or multiple parameter lists. At the callsite, the Scala compiler selects the appropriate foo method to call (and therefore the appropriate dummy object to pass in) by looking at the type of the list being passed in (which isn't erased until later).
While it's more verbose, this approach relieves the caller of the burden of supplying the implicit arguments. In fact, it even works if the dummyN objects are private to the TestDoubleDef class.
Due to the wonders of type erasure, the type parameters of your methods' List get erased during compilation, thus reducing both methods to the same signature, which is a compiler error.
As Viktor Klang already says, the generic type will be erased by the compiler. Fortunately, there's a workaround:
class TestDoubleDef{
def foo(p:List[String])(implicit ignore: String) = {}
def foo(p:List[Int])(implicit ignore: Int) = {}
}
object App extends Application {
implicit val x = 0
implicit val y = ""
val a = new A()
a.foo(1::2::Nil)
a.foo("a"::"b"::Nil)
}
Thanks for Michid for the tip!
If I combine Daniels response and Sandor Murakozis response here I get:
#annotation.implicitNotFound(msg = "Type ${T} not supported only Int and String accepted")
sealed abstract class Acceptable[T]; object Acceptable {
implicit object IntOk extends Acceptable[Int]
implicit object StringOk extends Acceptable[String]
}
class TestDoubleDef {
def foo[A : Acceptable : Manifest](p:List[A]) = {
val m = manifest[A]
if (m equals manifest[String]) {
println("String")
} else if (m equals manifest[Int]) {
println("Int")
}
}
}
I get a typesafe(ish) variant
scala> val a = new TestDoubleDef
a: TestDoubleDef = TestDoubleDef#f3cc05f
scala> a.foo(List(1,2,3))
Int
scala> a.foo(List("test","testa"))
String
scala> a.foo(List(1L,2L,3L))
<console>:21: error: Type Long not supported only Int and String accepted
a.foo(List(1L,2L,3L))
^
scala> a.foo("test")
<console>:9: error: type mismatch;
found : java.lang.String("test")
required: List[?]
a.foo("test")
^
The logic may also be included in the type class as such (thanks to jsuereth):
#annotation.implicitNotFound(msg = "Foo does not support ${T} only Int and String accepted")
sealed trait Foo[T] { def apply(list : List[T]) : Unit }
object Foo {
implicit def stringImpl = new Foo[String] {
def apply(list : List[String]) = println("String")
}
implicit def intImpl = new Foo[Int] {
def apply(list : List[Int]) = println("Int")
}
}
def foo[A : Foo](x : List[A]) = implicitly[Foo[A]].apply(x)
Which gives:
scala> #annotation.implicitNotFound(msg = "Foo does not support ${T} only Int and String accepted")
| sealed trait Foo[T] { def apply(list : List[T]) : Unit }; object Foo {
| implicit def stringImpl = new Foo[String] {
| def apply(list : List[String]) = println("String")
| }
| implicit def intImpl = new Foo[Int] {
| def apply(list : List[Int]) = println("Int")
| }
| } ; def foo[A : Foo](x : List[A]) = implicitly[Foo[A]].apply(x)
defined trait Foo
defined module Foo
foo: [A](x: List[A])(implicit evidence$1: Foo[A])Unit
scala> foo(1)
<console>:8: error: type mismatch;
found : Int(1)
required: List[?]
foo(1)
^
scala> foo(List(1,2,3))
Int
scala> foo(List("a","b","c"))
String
scala> foo(List(1.0))
<console>:32: error: Foo does not support Double only Int and String accepted
foo(List(1.0))
^
Note that we have to write implicitly[Foo[A]].apply(x) since the compiler thinks that implicitly[Foo[A]](x) means that we call implicitly with parameters.
There is (at least one) another way, even if it is not too nice and not really type safe:
import scala.reflect.Manifest
object Reified {
def foo[T](p:List[T])(implicit m: Manifest[T]) = {
def stringList(l: List[String]) {
println("Strings")
}
def intList(l: List[Int]) {
println("Ints")
}
val StringClass = classOf[String]
val IntClass = classOf[Int]
m.erasure match {
case StringClass => stringList(p.asInstanceOf[List[String]])
case IntClass => intList(p.asInstanceOf[List[Int]])
case _ => error("???")
}
}
def main(args: Array[String]) {
foo(List("String"))
foo(List(1, 2, 3))
}
}
The implicit manifest paramenter can be used to "reify" the erased type and thus hack around erasure. You can learn a bit more about it in many blog posts,e.g. this one.
What happens is that the manifest param can give you back what T was before erasure. Then a simple dispatch based on T to the various real implementation does the rest.
Probably there is a nicer way to do the pattern matching, but I haven't seen it yet. What people usually do is matching on m.toString, but I think keeping classes is a bit cleaner (even if it's a bit more verbose). Unfortunately the documentation of Manifest is not too detailed, maybe it also has something that could simplify it.
A big disadvantage of it is that it's not really type safe: foo will be happy with any T, if you can't handle it you will have a problem. I guess it could be worked around with some constraints on T, but it would further complicate it.
And of course this whole stuff is also not too nice, I'm not sure if it worth doing it, especially if you are lazy ;-)
Instead of using manifests you could also use dispatchers objects implicitly imported in a similar manner. I blogged about this before manifests came up: http://michid.wordpress.com/code/implicit-double-dispatch-revisited/
This has the advantage of type safety: the overloaded method will only be callable for types which have dispatchers imported into the current scope.
Nice trick I've found from http://scala-programming-language.1934581.n4.nabble.com/disambiguation-of-double-definition-resulting-from-generic-type-erasure-td2327664.html
by Aaron Novstrup
Beating this dead horse some more...
It occurred to me that a cleaner hack is to use a unique dummy type
for each method with erased types in its signature:
object Baz {
private object dummy1 { implicit val dummy: dummy1.type = this }
private object dummy2 { implicit val dummy: dummy2.type = this }
def foo(xs: String*)(implicit e: dummy1.type) = 1
def foo(xs: Int*)(implicit e: dummy2.type) = 2
}
[...]
I tried improving on Aaron Novstrup’s and Leo’s answers to make one set of standard evidence objects importable and more terse.
final object ErasureEvidence {
class E1 private[ErasureEvidence]()
class E2 private[ErasureEvidence]()
implicit final val e1 = new E1
implicit final val e2 = new E2
}
import ErasureEvidence._
class Baz {
def foo(xs: String*)(implicit e:E1) = 1
def foo(xs: Int*)(implicit e:E2) = 2
}
But that will cause the compiler to complain that there are ambiguous choices for the implicit value when foo calls another method which requires an implicit parameter of the same type.
Thus I offer only the following which is more terse in some cases. And this improvement works with value classes (those that extend AnyVal).
final object ErasureEvidence {
class E1[T] private[ErasureEvidence]()
class E2[T] private[ErasureEvidence]()
implicit def e1[T] = new E1[T]
implicit def e2[T] = new E2[T]
}
import ErasureEvidence._
class Baz {
def foo(xs: String*)(implicit e:E1[Baz]) = 1
def foo(xs: Int*)(implicit e:E2[Baz]) = 2
}
If the containing type name is rather long, declare an inner trait to make it more terse.
class Supercalifragilisticexpialidocious[A,B,C,D,E,F,G,H,I,J,K,L,M] {
private trait E
def foo(xs: String*)(implicit e:E1[E]) = 1
def foo(xs: Int*)(implicit e:E2[E]) = 2
}
However, value classes do not allow inner traits, classes, nor objects. Thus also note Aaron Novstrup’s and Leo’s answers do not work with a value classes.
I didn't test this, but why wouldn't an upper bound work?
def foo[T <: String](s: List[T]) { println("Strings: " + s) }
def foo[T <: Int](i: List[T]) { println("Ints: " + i) }
Does the erasure translation to change from foo( List[Any] s ) twice, to foo( List[String] s ) and foo( List[Int] i ):
http://www.angelikalanger.com/GenericsFAQ/FAQSections/TechnicalDetails.html#FAQ108
I think I read that in version 2.8, the upper bounds are now encoded that way, instead of always an Any.
To overload on covariant types, use an invariant bound (is there such a syntax in Scala?...ah I think there isn't, but take the following as conceptual addendum to the main solution above):
def foo[T : String](s: List[T]) { println("Strings: " + s) }
def foo[T : String2](s: List[T]) { println("String2s: " + s) }
then I presume the implicit casting is eliminated in the erased version of the code.
UPDATE: The problem is that JVM erases more type information on method signatures than is "necessary". I provided a link. It erases type variables from type constructors, even the concrete bound of those type variables. There is a conceptual distinction, because there is no conceptual non-reified advantage to erasing the function's type bound, as it is known at compile-time and does not vary with any instance of the generic, and it is necessary for callers to not call the function with types that do not conform to the type bound, so how can the JVM enforce the type bound if it is erased? Well one link says the type bound is retained in metadata which compilers are supposed to access. And this explains why using type bounds doesn't enable overloading. It also means that JVM is a wide open security hole since type bounded methods can be called without type bounds (yikes!), so excuse me for assuming the JVM designers wouldn't do such an insecure thing.
At the time I wrote this, I didn't understand that stackoverflow was a system of rating people by quality of answers like some competition over reputation. I thought it was a place to share information. At the time I wrote this, I was comparing reified and non-reified from a conceptual level (comparing many different languages), and so in my mind it didn't make any sense to erase the type bound.