I seems that combining implicit conversions with generic implicit parameters does not work, as in example 2b below:
object Test {
case class Foo(i: Int)
case class Bar(i: Int)
case class Zip(i: Int)
object Foo {
// 1)
implicit def toBar(foo: Foo)(implicit g: Int => Bar): Bar = g(foo.i)
// 2)
implicit def toT[T](foo: Foo)(implicit g: Int => T): T = g(foo.i)
}
// 1)
implicit val b = (i: Int) => Bar(i)
val bar: Bar = Foo(3)
// 2a)
implicit val z = (i: Int) => Zip(i)
val zip: Zip = Foo.toT(Foo(3))
// 2b)
val zip2: Zip = Foo(3) // <- compiler error, implicit conversion not applied
}
Is there any theoretical reason why this doesn't work, or is it a limitation of the implementation?
For what it's worth, if you run the following reduced version of your code
case class Foo(i: Int)
case class Zip(i: Int)
implicit def toT[T](foo: Foo)(implicit g: Int => T): T = g(foo.i)
implicit val z = (i: Int) => Zip(i)
val zip2: Zip = Foo(3) // <- compiler error, implicit conversion not applied
with -Yinfer-debug, you'll get lots of debug information (Scala 2.9.2) about what is going on behind the scenes. I am not familiar with Scala compiler internals, but the following two output snippets might hint at the problem. The first one is (line 51ff of the gist)
[inferImplicit view] pt = this.Foo => this.Zip
Implicit search in Context(Main.$anon.zip2#ValDef scope=1100551785) {
search this.Foo => this.Zip
target $anon.this.Foo.apply(3)
isView true
eligible toT: [T](foo: this.Foo)(implicit g: Int => T)T
}
and I interpret it as "we are looking for an implicit this.Foo => this.Zip and a candidate worth looking at is toT: [T](foo: this.Foo)(implicit g: Int => T)T.
This snippet is followed by output that suggests that Scala then tries to instantiate T, but line 81 finally says
inferMethodInstance, still undetermined: List(type T)
My interpretation is, that Scala somehow fails to instantiate T with Zip, which is why the candidate is finally discarded.
That said, I don't see a theoretical problem with your code, and I assume that it is only a shortcoming of the compiler.
Related
Scala compiler detects the following two map functions as duplicates conflicting with each other:
class ADT {
def map[Output <: AnyVal](f: Int => Output): List[Output] = ???
def map[Output >: Null <: AnyRef](f: Int => Output): List[Output] = ???
}
The class type of Output parameter is different. First one limits to AnyVal and second one limits to AnyRef. How can I differentiate them?
The problem is not differentiating AnyVal from AnyRef so much as getting around the fact that both method signatures become the same after erasure.
Here is a neat trick to get around this kind of problem. It is similar to what #som-snytt did, but a bit more generic, as it works for other similar situations as well (e.g. def foo(f: Int => String): String = ??? ; def foo(f: String => Int): Int = ??? etc.):
class ADT {
def map[Output <: AnyVal](f: Int => Output): List[Output] = ???
def map[Output >: Null <: AnyRef](f: Int => Output)(implicit dummy: DummyImplicit): List[Output] = ???
}
The cutest thing is that this works "out of the box". Apparently, a DummyImplicit is a part of standard library, and you always have the thing in scope.
You can have more than two overloads this way too by just adding more dummies to the list.
scala 2.13.0-M5> :pa
// Entering paste mode (ctrl-D to finish)
object X {
def map[Output <: AnyVal](f: Int => Output) = 1
def map[O](f: Int => O)(implicit ev: O <:< AnyRef) = 2
}
// Exiting paste mode, now interpreting.
defined object X
scala 2.13.0-M5> X.map((x: Int) => x*2)
res0: Int = 1
scala 2.13.0-M5> X.map((x: Int) => "")
res1: Int = 2
You could use a typeclass for that map method.
Using your exact example:
trait MyTC[Output]{
def map(f: Int => Output): List[Output]
}
object MyTC{
def apply[A](a : A)(implicit ev : MyTC[A]) : MyTC[A] = ev
implicit def anyRefMyTc[A <: AnyRef] : MyTC[A] = new MyTC[A]{
def map(f: Int => A): List[A] = { println("inside sub-AnyRef"); List.empty }
}
implicit def anyValMyTc[A <: AnyVal] : MyTC[A] = new MyTC[A]{
def map(f: Int => A): List[A] = { println("inside sub-AnyVal"); List.empty }
}
}
import MyTC._
val r1 = Option("Test1")
val r2 = List(5)
val v1 = true
val v2 = 6L
// The functions here are just to prove the point, and don't do anything.
MyTC(r1).map(_ => None)
MyTC(r2).map(_ => List.empty)
MyTC(v1).map(_ => false)
MyTC(v2).map(_ => 10L)
That would print:
inside sub-AnyRef
inside sub-AnyRef
inside sub-AnyVal
inside sub-AnyVal
The advantage of this approach is that, should you then choose to specialise the behaviour further for just some specific type (e.g. say you want to do something specific for Option[String]), you can do that easily:
// This is added to MyTC object
implicit val optMyTc : MyTC[Option[String]] = new MyTC[Option[String]]{
def map(f: Int => Option[String]): List[Option[String]] = { println("inside Option[String]"); List.empty }
}
Then, re-running the code will print:
inside Option[String]
inside sub-AnyRef
inside sub-AnyVal
inside sub-AnyVal
I'm using a ConcurrentHashMap in Scala and I would like to use the computeIfAbsent() method but can't figure out the syntax for the second argument. Can someone show me what would be the proper syntax?
When running the following code
val data = new ConcurrentHashMap[String, LongAdder]
data.computeIfAbsent("bob", k: String => new LongAdder()).increment()
I'm getting the following error
Type mismatch, expected: Function[_ >: String, _ <: LongAdder], actual: (String) => Any
Thanking you in advance
Francis
The problem is that you're using java.util.concurrent.ConcurrentHashMap, which accepts java.util.function.Function as a parameter for computeIfAbsent() instead of scala.Function1 which you pass to it.
Since scala doesn't support lambda conversion for functional interfaces as Java does (at least not without the -Xexperimental flag), you can solve this by implementing a java.util.function.Function explicitly:
val data = new ConcurrentHashMap[String, LongAdder]
val adderSupplier = new java.util.function.Function[String, LongAdder]() {
override def apply(t: String): LongAdder = new LongAdder()
}
data.computeIfAbsent("bob", adderSupplier).increment()
Alternatively, if you need this more often, you may write a utility conversion function or even an implicit conversion:
object FunctionConverter {
implicit def scalaFunctionToJava[From, To](function: (From) => To): java.util.function.Function[From, To] = {
new java.util.function.Function[From, To] {
override def apply(input: From): To = function(input)
}
}
}
import FunctionConverter._
val data = new ConcurrentHashMap[String, LongAdder]()
data.computeIfAbsent("bob", (k: String) => new LongAdder()) // <- implicit conversion applied here
If you enable -Xexperimental flag you can use scala anonymous function notation for this:
scala> val data = new java.util.concurrent.ConcurrentHashMap[String, Int]
data: java.util.concurrent.ConcurrentHashMap[String,Int] = {}
scala> data.computeIfAbsent("bob", _.size)
res0: Int = 3
Note that you still can't pass regular scala Function
scala> val f: String => Int = _.size
f: String => Int = <function1>
scala> data.computeIfAbsent("bob", f)
<console>:13: error: type mismatch;
found : String => Int
required: java.util.function.Function[_ >: String, _ <: Int]
data.computeIfAbsent("bob", f)
^
But eta-expansion will work
scala> def a(s: String): Int = s.size
a: (s: String)Int
scala> data.computeIfAbsent("bob", a)
res3: Int = 3
Essentially, what I would like to do is write overloaded versions of "map" for a custom class such that each version of map differs only by the type of function passed to it.
This is what I would like to do:
object Test {
case class Foo(name: String, value: Int)
implicit class FooUtils(f: Foo) {
def string() = s"${f.name}: ${f.value}"
def map(func: Int => Int) = Foo(f.name, func(f.value))
def map(func: String => String) = Foo(func(f.name), f.value)
}
def main(args: Array[String])
{
def square(n: Int): Int = n * n
def rev(s: String): String = s.reverse
val f = Foo("Test", 3)
println(f.string)
val g = f.map(rev)
val h = g.map(square)
println(h.string)
}
}
Of course, because of type erasure, this won't work. Either version of map will work alone, and they can be named differently and everything works fine. However, it is very important that a user can call the correct map function simply based on the type of the function passed to it.
In my search for how to solve this problem, I cam across TypeTags. Here is the code I came up with that I believe is close to correct, but of course doesn't quite work:
import scala.reflect.runtime.universe._
object Test {
case class Foo(name: String, value: Int)
implicit class FooUtils(f: Foo) {
def string() = s"${f.name}: ${f.value}"
def map[A: TypeTag](func: A => A) =
typeOf[A] match {
case i if i =:= typeOf[Int => Int] => f.mapI(func)
case s if s =:= typeOf[String => String] => f.mapS(func)
}
def mapI(func: Int => Int) = Foo(f.name, func(f.value))
def mapS(func: String => String) = Foo(func(f.name), f.value)
}
def main(args: Array[String])
{
def square(n: Int): Int = n * n
def rev(s: String): String = s.reverse
val f = Foo("Test", 3)
println(f.string)
val g = f.map(rev)
val h = g.map(square)
println(h.string)
}
}
When I attempt to run this code I get the following errors:
[error] /src/main/scala/Test.scala:10: type mismatch;
[error] found : A => A
[error] required: Int => Int
[error] case i if i =:= typeOf[Int => Int] => f.mapI(func)
[error] ^
[error] /src/main/scala/Test.scala:11: type mismatch;
[error] found : A => A
[error] required: String => String
[error] case s if s =:= typeOf[String => String] => f.mapS(func)
It is true that func is of type A => A, so how can I tell the compiler that I'm matching on the correct type at runtime?
Thank you very much.
In your definition of map, type A means the argument and result of the function. The type of func is then A => A. Then you basically check that, for example typeOf[A] =:= typeOf[Int => Int]. That means func would be (Int => Int) => (Int => Int), which is wrong.
One of ways of fixing this using TypeTags looks like this:
def map[T, F : TypeTag](func: F)(implicit ev: F <:< (T => T)) = {
func match {
case func0: (Int => Int) #unchecked if typeOf[F] <:< typeOf[Int => Int] => f.mapI(func0)
case func0: (String => String) #unchecked if typeOf[F] <:< typeOf[String => String] => f.mapS(func0)
}
}
You'd have to call it with an underscore though: f.map(rev _). And it may throw match errors.
It may be possible to improve this code, but I'd advise to do something better. The simplest way to overcome type erasure on overloaded method arguments is to use DummyImplicit. Just add one or several implicit DummyImplicit arguments to some of the methods:
implicit class FooUtils(f: Foo) {
def string() = s"${f.name}: ${f.value}"
def map(func: Int => Int)(implicit dummy: DummyImplicit) = Foo(f.name, func(f.value))
def map(func: String => String) = Foo(func(f.name), f.value)
}
A more general way to overcome type erasure on method arguments is to use the magnet pattern. Here is a working example of it:
sealed trait MapperMagnet {
def map(foo: Foo): Foo
}
object MapperMagnet {
implicit def forValue(func: Int => Int): MapperMagnet = new MapperMagnet {
override def map(foo: Foo): Foo = Foo(foo.name, func(foo.value))
}
implicit def forName(func: String => String): MapperMagnet = new MapperMagnet {
override def map(foo: Foo): Foo = Foo(func(foo.name), foo.value)
}
}
implicit class FooUtils(f: Foo) {
def string = s"${f.name}: ${f.value}"
// Might be simply `def map(func: MapperMagnet) = func.map(f)`
// but then it would require those pesky underscores `f.map(rev _)`
def map[T](func: T => T)(implicit magnet: (T => T) => MapperMagnet): Foo =
magnet(func).map(f)
}
This works because when you call map, the implicit magnet is resolved at compile time using full type information, so no erasure happens and no runtime type checks are needed.
I think the magnet version is cleaner, and as a bonus it doesn't use any runtime reflective calls, you can call map without underscore in the argument: f.map(rev), and also it can't throw runtime match errors.
Update:
Now that I think of it, here magnet isn't really simpler than a full typeclass, but it may show the intention a bit better. It's a less known pattern than typeclass though. Anyway, here is the same example using the typeclass pattern for completeness:
sealed trait FooMapper[F] {
def map(foo: Foo, func: F): Foo
}
object FooMapper {
implicit object ValueMapper extends FooMapper[Int => Int] {
def map(foo: Foo, func: Int => Int) = Foo(foo.name, func(foo.value))
}
implicit object NameMapper extends FooMapper[String => String] {
def map(foo: Foo, func: String => String) = Foo(func(foo.name), foo.value)
}
}
implicit class FooUtils(f: Foo) {
def string = s"${f.name}: ${f.value}"
def map[T](func: T => T)(implicit mapper: FooMapper[T => T]): Foo =
mapper.map(f, func)
}
I want to be able to define a method with the same name that has a different implementation if the argument is an Iterable[T1] vs a function: T1 => T2
However, many classes that implement Iterable also implement PartialFunction
For example:
object FunList {
def foo(itr: Iterable[Int]) = println("hello")
def foo(f: (Int => Int)) = println("Goodbye")
}
scala> FunList.foo(List(1))
<console>:9: error: ambiguous reference to overloaded definition,
both method foo in object FunList of type (f: Int => Int)Unit
and method foo in object FunList of type (itr: Iterable[Int])Unit
match argument types (List[Int])
FunList.foo(List(1))
currently my solution looks like this, but it does not match subclasses of Iterable which are not also subclasses of PartialFunction
case class SeqOrFun[T1, T2](f: (T1 => T2))
implicit def seqOrFun[T1, T2](f: (T1 => T2)) = SeqOrFun(f)
def unfurl[T1: Numeric, T2: Numeric](x: SeqOrFun[T1, T2], y: SeqOrFun[T1, T2]) = {
(x.f, y.f) match {
case (xs: Iterable[T1], ys: Iterable[T2]) => (xs, ys)
case (xf: (T2 => T1), ys: Iterable[T2]) => (ys.map(xf), ys)
case (xs: Iterable[T1], yf: (T1 => T2)) => (xs, xs.map(yf))
}
}
Since List is both Iterable[Int] and Int => Int, as you've said, what you're writing is inherently abmiguous. Perhaps I've misread, but I don't see any place at all where you've specified whether you want FunList.foo(List(1)) to print "hello" or "Goodbye".
First, you can use a cast at the call site. I assume you already know this, but just to be explicit for the sake of discussion:
FunList.foo(List(1): Int => Int) // "hello"
FunList.foo(List(1): Iterable[Int]) // "Goodbye"
If our objective here is to allow the caller to simply write FunList.foo(List(1)), you could use the magnet pattern. This means you don't use method overloading at all; instead you write a single method, and the dispatch is done with implicit conversions.
sealed trait FooMagnet
case class HelloMagnet(itr: Iterable[Int]) extends FooMagnet
case class GoodbyeMagnet(f: Int => Int) extends FooMagnet
def foo(x: FooMagnet): Unit = x match {
case HelloMagnet(itr) => println("hello")
case GoodbyeMagnet(f) => println("Goodbye")
}
def a(): Unit = {
implicit def listIsHelloMagnet(x: List[Int]): FooMagnet = HelloMagnet(x)
FunList.foo(List(1)) // "hello"
}
def b(): Unit = {
implicit def listIsGoodbyeMagnet(x: List[Int]): FooMagnet = GoodbyeMagnet(x)
FunList.foo(List(1)) // "Goodbye"
}
The fun advantage you get here is that the dispatch decision is decoupled from the foo implementation, since it's determined by those implicits which you can define wherever you like.
You can also use this to resolve the ambiguity problem! Start with the two implicits from earlier:
implicit def iterableIsHelloMagnet(x: Iterable[Int]): FooMagnet = HelloMagnet(x)
implicit def functionIsGoodbyeMagnet(x: Int => Int): FooMagnet = GoodbyeMagnet(x)
And then add another implicit specifically for List[Int].
implicit def listIsHelloMagnet(x: List[Int]): FooMagnet = HelloMagnet(x)
Scala is clever enough to see that this third conversion is more specific than the first two, so it will use that one for List[Int] even though they all apply. Thus we can now write:
FunList.foo(Set(1)) // "hello"
FunList.foo((_: Int) + 1) // "Goodbye"
FunList.foo(List(1)) // "hello"
And you can move the definitions of those implicits into the called library, so all the caller has to do is import them.
Forgive me if this question is a duplicate; I'm having trouble finding anything because I don't know the right words to search. So, with implicit def, I can do things like this:
type CharsetMap = Map[Charset, Byte]
implicit def seqtup2CharsetMap(input: Seq[(String, Int)]): CharsetMap = {
Map.empty // placeholder
}
def somef(a: Int, b:Int, p: CharsetMap) = p
somef(1, 3, Seq(("hey", 2), ("there", 9)))
which lets me call somef with a Seq[(String, Int)] object as a parameter. The problem is that I have something like this...
def somef2(p: (CharsetMap) => Int) = p
and this does not work:
val p = (a: Seq[(String, Int)]) => 19
somef2(p)
How can I do this without doing an implicit def specifically for (Seq[(String, Int)]) => Int?
It looks like you want to implicitly convert some function A => B to a function that goes from C => B. You can do that with this generic implicit:
implicit def f2InputConverter[A, B, C](f: A => B)(implicit i: C => A): C => B = (c: C) => f(i(c))
Once you have that in scope, in your particular case, you'll need an implicit function which is the inverse of the one that you've defined in the question:
implicit def charsetMap2Seqtup(input: CharsetMap): Seq[(String, Int)] = {
Nil // placeholder
}
and then you should be able to call somef2 with p