Scala implicit conversion of apply method - scala

I tried the following to create an option-checking style in code:
object Test {
trait Check
object x extends Check
def option() = false
def option(xx: Check) = true
implicit class AugmentCheck(s: String) {
def apply() = ""
def apply(xx: Check) = s
}
}
import Test._
val delete = option ( x )
val force = option ( )
val res = "mystring" ( )
But I face the following problem:
<console>:11: error: type mismatch;
found : String("mystring")
required: ?{def apply: ?}
Note that implicit conversions are not applicable because they are ambiguous:
both method augmentString in object Predef of type (x: String)scala.collection.
immutable.StringOps
and method AugmentCheck in object Test of type (s: String)Test.AugmentCheck
are possible conversion functions from String("mystring") to ?{def apply: ?}
val res = "mystring" ( )
^
<console>:11: error: String("mystring") does not take parameters
val res = "mystring" ( )
This is unfortunate, because even if there is ambiguity in the symbol name, there shouldn't be any ambiguity in the function signature.
If I introduce the method "apply", it works fine when there is an argument, but not without:
val res = "mystring" apply ( x )
res == ""
How can I remove the keyword "apply" in this case?

Instead of representing the on and off states with x or  , what about using y for yes and n for no?
object Test {
val y = true
val n = false
class DefaultConfigValue[U](val v: U)
implicit class ConfigValue[U](v: U) {
def y = v
def n(implicit default: DefaultConfigValue[U]) = default.v
}
implicit val defaultConfigString = new DefaultConfigValue("")
}
import Test._
import language.postfixOps
val delete = y
val force = n
val res1 = "my first string" y
val res2 = "my second string" n
Notice how you can import postfixOps and then just add extra whitespace to align all the ys and ns for your string configuration options into the same column.
I'm not sure if this makes sense, but I wrote the above code such that you should be able to use any type (not just strings) for the options with the y and n postfix operators. All you have to do to enable a new type is create an implicit DefaultConfigValue for that type so that the no option has something to return.

I'd strongly recommend against using this pattern, as it violates the principle of least surprise.
StringOps already defines apply(n) on a String to return the Nth character, any other overload is going to confuse a lot of people. Even in the context of a DSL.
Option is also a well-understood term, whose meaning is overloaded here.
Finally: x is very commonly used as a parameter to methods and as a bound value in pattern-matching. Using it in a wide scope like this is going to cause a lot of shadowing, and risks causing some very unexpected error messages.
Can you give a better idea of what you're trying to achieve so that we can suggest some better alternatives?

Related

scala overloading resolution differences between function calls and implicit search

There is a difference in the way the scala 2.13.3 compiler determines which overloaded function to call compared to which overloaded implicit to pick.
object Thing {
trait A;
trait B extends A;
trait C extends A;
def f(a: A): String = "A"
def f(b: B): String = "B"
def f(c: C): String = "C"
implicit val a: A = new A {};
implicit val b: B = new B {};
implicit val c: C = new C {};
}
import Thing._
scala> f(new B{})
val res1: String = B
scala> implicitly[B]
val res2: Thing.B = Thing$$anon$2#2f64f99f
scala> f(new A{})
val res3: String = A
scala> implicitly[A]
^
error: ambiguous implicit values:
both value b in object Thing of type Thing.B
and value c in object Thing of type Thing.C
match expected type Thing.A
As we can see, the overload resolution worked for the function call but not for the implicit pick. Why isn't the implicit offered by val a be chosen as occurs with function calls? If the callers ask for an instance of A why the compilers considers instances of B and C when an instance of A is in scope. There would be no ambiguity if the resolution logic were the same as for function calls.
Edit 2:
The Edit 1 was removed because the assertion I wrote there was wrong.
In response to the comments I added another test to see what happens when the implicit val c: C is removed. In that case the compiler don't complains and picks implicit val b: B despite the caller asked for an instance of A.
object Thing {
trait A { def name = 'A' };
trait B extends A { def name = 'B' };
trait C extends A { def name = 'C' };
def f(a: A): String = "A"
def f(b: B): String = "B"
implicit val a: A = new A {};
implicit val b: B = new B {};
}
import Thing._
scala> f(new A{})
val res0: String = A
scala> implicitly[A].name
val res3: Char = B
So, the overloading resolution of implicit differs from function calls more than I expected.
Anyway, I still don't find a reason why the designers of scala decided to apply a different resolution logic for function and implicit overloading. (Edit: Later noticed why).
Let's see what happens in a real world example.
Suppose we are doing a Json parser that converts a Json string directly to scala Abstract data types, and we want it to support many standard collections.
The snippet in charge of parsing the iterable collections would be something like this:
trait Parser[+A] {
def parse(input: Input): ParseResult;
///// many combinators here
}
implicit def summonParser[T](implicit parserT: Parser[T]) = parserT;
/** #tparam IC iterator type constructor
* #tparam E element's type */
implicit def iterableParser[IC[E] <: Iterable[E], E](
implicit
parserE: Parser[E],
factory: IterableFactory[IC]
): Parser[IC[E]] = '[' ~> skipSpaces ~> (parserE <~ skipSpaces).repSepGen(coma <~ skipSpaces, factory.newBuilder[E]) <~ skipSpaces <~ ']';
Which requires a Parser[E] for the elements and a IterableFactory[IC] to construct the collection specified by the type parameters.
So, we have to put in implicit scope an instance of IterableFactory for every collection type we want to support.
implicit val iterableFactory: IterableFactory[Iterable] = Iterable
implicit val setFactory: IterableFactory[Set] = Set
implicit val listFactory: IterableFactory[List] = List
With the current implicit resolution logic implemented by the scala compiler, this snippet works fine for Set and List, but not for Iterable.
scala> def parserInt: Parser[Int] = ???
def parserInt: read.Parser[Int]
scala> Parser[List[Int]]
val res0: read.Parser[List[Int]] = read.Parser$$anonfun$pursue$3#3958db82
scala> Parser[Vector[Int]]
val res1: read.Parser[Vector[Int]] = read.Parser$$anonfun$pursue$3#648f48d3
scala> Parser[Iterable[Int]]
^
error: could not find implicit value for parameter parserT: read.Parser[Iterable[Int]]
And the reason is:
scala> implicitly[IterableFactory[Iterable]]
^
error: ambiguous implicit values:
both value listFactory in object IterableParser of type scala.collection.IterableFactory[List]
and value vectorFactory in object IterableParser of type scala.collection.IterableFactory[Vector]
match expected type scala.collection.IterableFactory[Iterable]
On the contrary, if the overloading resolution logic of implicits was like the one for function calls, this would work fine.
Edit 3: After many many coffees I noticed that, contrary to what I said above, there is no difference between the way the compiler decides which overloaded functions to call and which overloaded implicit to pick.
In the case of function call: from all the functions overloads such that the type of the argument is asignable to the type of the parameter, the compiler chooses the one such that the function's parameter type is assignable to all the others. If no function satisfies that, a compilation error is thrown.
In the case of implicit pick up: from all the implicit in scope such that the type of the implicit is asignable to the asked type, the compiler chooses the one such that the declared type is asignable to all the others. If no implicit satisfies that, an compilation error is thrown.
My mistake was that I didn't notice the inversion of the assignability.
Anyway, the resolution logic I proposed above (give me what I asked for) is not entirely wrong. It's solves the particular case I mentioned. But for most uses cases the logic implemented by the scala compiler (and, I suppose, all the other languages that support type classes) is better.
As explained in the Edit 3 section of the question, there are similitudes between the way the compiler decides which overloaded functions to call and which overloaded implicit to pick. In both cases the compiler does two steps:
Filters out all the alternatives that are not asignable.
From the remaining alternatives choses the most specific or complains if there is more than one.
In the case of the function call, the most specific alternative is the function with the most specific parameter type; and in the case of implicit pick is the instance with the most specific declared type.
But, if the logic in both cases were exactly the same, then why did the example of the question give different results? Because there is a difference: the assignability requirement that determines which alternatives pass the first step are oposite.
In the case of the function call, after the first step remain the functions whose parameter type is more generic than the argument type; and in the case of implicit pick, remain the instances whose declared type is more specific than the asked type.
The above words are enough to answers the question itself but don't give a solution to the problem that motivated it, which is: How to force the compiler to pick the implicit instance whose declared type is exactly the same than the summoned type? And the answer is: wrapping the implicit instances inside a non variant wrapper.

type annotations overriden by inferred expression type

In scala programming language, given I'll annotate an expression with some broader type and I provide an narrow value, my program is rejected:
scala> def x[A](): A = 8
<console>:11: error: type mismatch;
found : Int(8)
required: A
def x[A]() = 8: A
Whereas in ocaml, when I'll do the same, the program is accepted, but the type annotation of the expression is overriden by the type of narrower expression.
utop # let x (): 'a = 8 ;;
val x : unit -> int = <fun>
What is the difference between these type systems, that results in situation, where in one case the program is rejected whereas in the other it is accepted?
#craigfe actually just wrote a very accessible post about this yesterday, and I would highly recommend reading that.
But the short answer is that type variables in annotations in OCaml are unification variables, not polymorphic type constraints. They represent unknown types to be inferred by the compiler, which will prefer more general solutions and might infer it to be polymorphic, but if not possible will infer it to be a specific type.
In order to get the behaviour you expect, you have to explicitly indicate that the type variable should be universally quantified using 'a., usually read "for all a's":
utop # let x: 'a. unit -> 'a = fun () -> 8 ;;
^^^^^^^^^^^
Error: This definition has type unit -> int which is less general than
'a. unit -> 'a
I don't know ocaml at all. But according to: val x : unit -> int = <fun> it seems like ocaml can infer the return type of the function you declared, which is int.
In Scala, when you declare def x[A](): A you define a function, and let's elaborate what this function means:
The name of the function is x.
This function is generic, and expects to get a type A.
The function has no arguments.
The return type is A.
When returning in such a function 8, the compiler tries to cast 8 into an A unsuccessfully.
What you are trying to do is something like:
scala> def x[A](): Int = 8
x: [A]()Int
In Scala it's allowed not to specify return type, then it will be inferred
def x() = 8
x(): Int
If you do want to specify the return type then, I guess, you can emulate the OCaml behavior of type parameter in Scala with a helper class
val t = TypeOf(8)
def x(): t.A = t.a
case class TypeOf[_A](a: _A) {
type A = _A
}
or
val t = TypeOf(8)
def x(): t.A = 8
implicit class TypeOf[_A](a: _A) {
type A = _A
}
or even
def x(): TypeOf.`8`.A = 8
import scala.language.dynamics
import scala.language.experimental.macros
import scala.reflect.macros.whitebox
object TypeOf extends Dynamic {
def selectDynamic(term: String): Any = macro selectDynamicImpl
def selectDynamicImpl(c: whitebox.Context)(term: c.Tree): c.Tree = {
import c.universe._, internal.decorators._
val q"${termStr: String}" = term
val termType = c.typecheck(c.parse(termStr), silent = false).tpe
val resType = c.typecheck(tq"{ type A = $termType }", mode=c.TYPEmode, silent = false).tpe
q"()".setType(resType)
}
}
(motivated by shapeless.Witness.selectDynamic).
See also
T <: A, return T method

How does one obtain the type of the value that an AST represents?

I’m trying to write the following:
import scala.reflect.runtime.universe._
val value: Tree = /* some AST */
val tpe = typeOf(value) // This should be the result type of the AST.
// This is pseudocode. What should
// actually go on this line?
q"""
type U = $tpe
val v: U = $value
"""
I need to capture the type of the value represented by the AST value in tpe and assign it to U. How does one do this?
Edit: Giving a type annotation for value and matching on it via quasiquotes isn't an option here. The use case is a Shapeless extensible record, which has complicated types such as String with labelled.KeyTag[1, String] :: Long with labelled.KeyTag[three, Long] :: HNil for something like val ls = (1 ->> "two") :: ("three" ->> 4L) :: HNil. Also, the value AST is programmatically generated and not a literal.
Get a ToolBox, use it to typecheck value, and ask the annotated tree for its type.
import scala.runtime.reflect.currentMirror
val toolbox = currentMirror.mkToolBox()
val tpe = TypeTree(toolbox.typecheck(value).tpe)
The code you've written states you're doing this at runtime. The use case you've stated in your comment makes it seem like you're in a compile-time macro. In that case, use the similar typecheck method in your Context. It won't typecheck otherwise; the value would be a Tree from the wrong Universe, representing the fact that the new compiler instance made by ToolBox operates in the context of the current program (which happens to be a compiler), while the reflection represented by the Context is all about the future context of the code manipulated by the containing compiler.
Try to use $tpt in q"$mods val $tname: $tpt = $expr"
val t: Tree = reify {
val value: Int = 3
}.tree
val tpe = t match {
case q"{$mods val $tname: $tpt = $expr; $_}" => tpt
} // Int
https://docs.scala-lang.org/overviews/quasiquotes/syntax-summary.html#definitions
Connected question: How does one use quasiquotes to obtain the type of a value?

Using Shapeless Polyfil to generically map over record

Akin to this question here (Mapping over Shapeless record), I am attempting to map over a trivial shapeless record (in this case, if I encounter a value of type Int, I want to convert it to a Double).
object Main extends App {
import shapeless._ ; import syntax.singleton._ ; import record._
import ops.record._
import syntax.singleton._
case class S(int:Int,t:String)
val s = S(3,"a")
val gen = LabelledGeneric[S]
val rec = gen.to(s)
val extended = rec + ('inPrint ->> true)
val removed = rec - 'int
val keys = Keys[gen.Repr]
val options =
('awesomeString ->> "a") ::
('epicInt ->> 5:Int) ::
HNil
def intToDouble(i:Int):Double = i.toDouble
object bind extends FieldPoly {
implicit def rpb[T, K](implicit witness: Witness.Aux[K]): Case.Aux[
FieldType[K, Int],
FieldType[K, Double]
] = atField(witness)(intToDouble)
}
val z = options.map(bind)
}
When I try to compile however, I get the following error
could not find implicit value for parameter mapper: shapeless.ops.hlist.Mapper[Main.bind.type,shapeless.::[String with shapeless.record.KeyTag[Symbol with shapeless.tag.Tagged[String("awesomeString")],String],shapeless.::[Int,shapeless.HNil]]]
Is there something critical that I am missing?
There's one very minor problem with your example. You have,
val options =
('awesomeString ->> "a") ::
('epicInt ->> 5:Int) ::
HNil
If you paste this into the REPL you'll see that you've lost track of the 'epicInt key in the last element of the record. This is because the type ascription binds less tightly than the ->> operator so you have, in effect, first tagged your value with its key and then immediately thrown it away again. This leaves you with a valid HList, but unfortunately not one which is the right shape to be a record. The fix is to either drop the type ascription altogether, or use parentheses (ie. (5: Int).
The bigger problem is your use of FieldPoly here. FieldPoly is intended for situations which the key you want to operate on is statically known. That's not the case here: the type variable K is free and would have to be inferred. Unfortunately there's no way that it can be: it would have to be inferred from the first argument to atField but that, in turn, depends on K via the implicit definition of witness.
It could be that a different variant of FieldPoly that better matches your scenario would be useful. In the meantime, an ordinary Poly1 which operates on whole fields (ie. the key combined with the value) will do what you want,
trait bind0 extends Poly1 {
implicit def default[E] = at[E](identity) // default case for non-Int fields
}
object bind extends bind0 {
implicit def caseInt[K] = // case for fields with Int values
at[FieldType[K, Int]](field[K](intToDouble _))
}

Scala: existential types for a Map

I want to use a map of varying types on an unknown A:
val map: Map[Foo[A], Bar[A]] = ...
...
val foo = new Foo[Qux]
val bar: Bar[Qux] = map(foo)
This doesn't work, because A is an unknown. I have to define it instead as:
val map: Map[Foo[_], Bar[_]] = ...
...
val foo = new Foo[Qux]
val bar: Bar[Qux] = map(foo).asInstanceOf[Bar[Qux]]
This works, but the cast is ugly. I'd rather find a better way. I gather the answer is to use existential types with the forSome keyword, but I'm confused as to how that works. Should it be:
Map[Foo[A], Bar[A]] forSome { type A }
or:
Map[Foo[A] forSome { type A }, Bar[A]]
or:
Map[Foo[A forSome { type A }], Bar[A]]
Actually, none of these work.
Map[Foo[A], Bar[A]] forSome { type A }
is a Map where all keys are of the same type Foo[A] and values of type Bar[A] (but the type A may be different for different maps of this type); in second and third examples, A in Bar[A] is completely different from A under forSome.
This ugly workaround should work:
// need type members, so can't use tuples
case class Pair[A, B](a: A, b: B) {
type T1 = A
type T2 = B
}
type PairedMap[P <: Pair[_, _]] = Map[P#T1, P#T2]
type FooBarPair[A] = Pair[Foo[A], Bar[A]]
val map: PairedMap[FooBarPair[_]] = ...
I want to use a map of varying types on an unknown A
So, you want a variant of Map[K,V] with following interface, correct?
trait DependentMap[K[_],V[_]] {
def add[A](key: K[A], value: V[A]): DependentMap[K,V]
def get[A](key: K[A]): Option[V[A]]
}
Whether it is or not might be a bit hard to tell from the type signature, so let's create a few dummy values and see if the type checker accepts what we want it to accept and rejects what we want it to reject.
// dummy definitions just to check that the types are correct
case class Foo[+A](a: A)
case class Bar[+A](a: A)
val myMap: DependentMap[Foo,Bar] = null
myMap.add(Foo( 42), Bar( 43)) // typechecks
myMap.add(Foo("foo"), Bar("bar")) // typechecks
myMap.add(Foo( 42), Bar("bar")) // type mismatch
val r1: Option[Bar[ Int]] = myMap.get(Foo( 42)) // typechecks
val r2: Option[Bar[String]] = myMap.get(Foo("foo")) // typechecks
val r3: Option[Bar[String]] = myMap.get(Foo( 42)) // type mismatch
So far so good. But look what happens once we start to play with inheritance:
val fooInt: Foo[Int] = Foo(42)
val fooAny: Foo[Any] = fooInt
val barStr: Bar[String] = Bar("bar")
val barAny: Bar[Any] = barStr
println(fooInt == fooAny) // true
myMap.add(fooAny, barAny).get(fooInt) // Bar("bar")?
Since fooInt and fooAny are the same value, we'd naïvely expect this get to succeed. According to the type signature of get, it would have to succeed with a value of type Bar[Int], but where would this value come from? The value we put in has the type Bar[Any] and also the type Bar[String], but certainly not the type Bar[Int]!
Here's another surprising case.
val fooListInt: Foo[List[Int]] = Foo(List[Int]())
val fooListStr: Foo[List[String]] = Foo(List[String]())
println(fooListInt == fooListStr) // true!
myMap.add(fooListInt, Bar(List(42))).get(fooListStr) // Bar(List(42))?
This time fooListInt and fooListStr look like they should be distinct, but in fact they both have the value Nil, of type List[Nothing], which is a subtype of both List[Int] and List[String]. So if we want to mimic the behaviour of Map[K,V] on such a key, get would again have to succeed, but it can't since we gave it a Bar[List[Int]] and it needs to produce a Bar[List[String]].
All this to say, our DependentMap should not consider keys to be equal unless the type A given to add is also equal to the type A given to get. Here is an implementation which uses type tags to ensure that this is the case.
import scala.reflect.runtime.universe._
class DependentMap[K[_],V[_]](
inner: Map[
(TypeTag[_], Any),
Any
] = Map()
) {
def add[A](
key: K[A], value: V[A]
)(
implicit tt: TypeTag[A]
): DependentMap[K,V] = {
val realKey: (TypeTag[_], Any) = (tt, key)
new DependentMap(inner + ((realKey, value)))
}
def get[A](key: K[A])(implicit tt: TypeTag[A]): Option[V[A]] = {
val realKey: (TypeTag[_], Any) = (tt, key)
inner.get(realKey).map(_.asInstanceOf[V[A]])
}
}
And here are a few examples demonstrating that it works as expected.
scala> val myMap: DependentMap[Foo,Bar] = new DependentMap
scala> myMap.add(Foo(42), Bar(43)).get(Foo(42))
res0: Option[Bar[Int]] = Some(Bar(43))
scala> myMap.add(Foo("foo"), Bar("bar")).get(Foo("foo"))
res1: Option[Bar[String]] = Some(Bar(bar))
scala> myMap.add(Foo(42), Bar("bar")).get(Foo(42))
error: type mismatch;
scala> myMap.add[Any](Foo(42), Bar("bar")).get(Foo(42))
res2: Option[Bar[Int]] = None
scala> myMap.add[Any](Foo(42), Bar("bar")).get[Any](Foo(42))
res3: Option[Bar[Any]] = Some(Bar(bar))
scala> myMap.add(Foo(List[Int]()), Bar(List(43))).get(Foo(List[Int]()))
res4: Option[Bar[List[Int]]] = Some(Bar(List(43)))
scala> myMap.add(Foo(List[Int]()), Bar(List(43))).get(Foo(List[String]()))
res5: Option[Bar[List[String]]] = None
This works, but the cast is ugly. I'd rather find a better way.
Then you're probably disappointed that my get is implemented using a cast. Let me try to convince you that there is no other way.
Instead of a map which may or may not contain our key, let's consider a much simpler case.
def safeCast[A,B](
value: A
)(
implicit tt1: TypeTag[A], tt2: TypeTag[B]
): Option[B] = {
if (tt1 == tt2)
Some(value.asInstanceOf[B])
else
None
}
Given a type tag for A and a type tag for B, if the two type tags are equal, then we know that A and B are the same type, and therefore the typecast is safe. But how could we possibly implement this without a typecast? The equality check returns a mere boolean, not a witness of equality like in some other languages. Therefore there is nothing which statically distinguishes the two branches of the if and the compiler cannot possibly know that a cast-free conversion is legal in the "true" branch but illegal in the other.
In the more complicated case of our DependentMap, we also have to compare our type tag with the one we stored when we did an add, and so we also have to use a cast.
I gather the answer is to use existential types with the forSome keyword
I can see why you'd think so. You want a bunch of associations from key to value, where each (key, value) pair has the type (Foo[A], Bar[A]) forSome {type A}. And indeed, if you were not concerned with performance, you could store those associations in a list:
val myList: List[(Foo[A], Bar[A]) forSome {type A}]
Since the forSome is inside the brackets, this allows each entry in the list to use a different A. And since Foo[A] and Bar[A] are both to the left of the forSome, in each entry the As must match.
In the case of Map, however, there is no place to put the forSome to obtain the result you want. The problem with Map is that it has two type parameters, which prevents us from from putting them both to the left of the forSome without putting the forSome outside of the brackets. It wouldn't make sense to do so: since the two type parameters are independent, there is nothing which links one occurrence of the left type parameter to a corresponding occurrence of the right type parameter, and so there is no way to know which As should match. Consider the following counter-example:
case class NotMap[K,V](k1: K, k2: K, v1: V, v2: V, v3: V)
There isn't the same number of K values as there are V values, so in particular there is no correspondence between the K values and the V values. If there was some special syntax like Map[{Foo[A], Bar[A]} forSome {type A}] which would allow us to specify that for each entry in the Map, the As should match, then it would also be possible to use that syntax to specify the nonsense type NotMap[{Foo[A], Bar[A]} forSome {type A}]. Therefore there is no such syntax, and we need to use a type other than Map, such as DependentMap or HMap.
What about something like
def map[A]: Map[Foo[A], Bar[A]] = ...
val myMap = map[Qux]
...
val foo = new Foo[Qux]
val bar: Bar[Qux] = myMap(foo)
Or (inspired by Alexey Romanov's answer)
type MyMap[A] = Map[Foo[A],Bar[A]]
val map:MyMap[Qux] = ...
...
val foo = new Foo[Qux]
val bar: Bar[Qux] = map(foo)