I have a javascript method that accepts js.Arrays that can contain objects of multiple types. E.g js.Dates or Integers or Strings
How I can model that without having to cast any of these types.
def domain(p: js.Array[js.Any])
does not work with
domain(js.Array(new js.Date(2015,1,1))
as js.Array is invariant.
def domain[T <: js.Any](p: js.Array[T])
does not work with
domain(js.Array("Test")) or domain(js.Array(0,2))
as String and Int do not inherit from js.Any.
I have seen that there is an implicit conversion from Int to js.Any but that does not seem to kick in
inferred type arguments [Int] do not conform to method domain's type
parameter bounds [T <: scala.scalajs.js.Any]
I am a bit puzzled anyway. Intellij does not show me an error while fastOptJS from sbt throws a compilation error.
Found the solution. Upper View Bounds:
def domain[T <% js.Any](p: js.Array[T])
Related
I want to get the name of a class passed as a parameter to a function using shapeless. I've tried this:
def sayMyName[T](t: T): String = Typeable[T].describe // error: class type required but T found
If T is replaced with a concrete type, there's no problem. Is it possible to make something like this work using shapeless?
You just need to add Typeable typeclass as context bound of your type T:
def sayMyName[T: Typeable](t: T): String = Typeable[T].describe
sayMyName("") //String
You could also explicitly declare implicit parameter:
def sayMyName[T](t: T)(implicit typeable: Typeable[T]): String = Typeable[T].describe
By adding context bound you're asking the compiler to wait with resolving Typeable
typeclass until sayMyName is called with the concrete type, not resolve it right away (which is impossible, since the real type of T is not yet known at this point).
Here is an example
def maybeeq[A <: String](x: A):A = x match {
case z:A => x
}
It produced the following error message during compilation
Error:(27, 12) scrutinee is incompatible with pattern type;
found : A
required: String
case z:A => x
I can put any final class into A's bound to reproduce the error.
Why this compiles for non-final classes but fails on the final? Why type erasure not just replace A with String?
Edited:
Note: such bound allows me to pass String-typed value to 'x' parameter. So 'x' can be just a String and don't have to be subtype of string, so I'm not asking compiler to compile method with incorrect signature. In the real-world code I would just put String instead on A parameter, but from the experimental perspective I'm interested why such extra restriction on top of existing restriction (based on final class nature) is needed.
TBH this is a question about compiler design which can only be answered by those who implemented such check
There is a test in compiler test suite that requires such error to be shown. It has something to do with type information being discarded to a point where a concrete type cannot be assigned to variable, but the reasons for that cannot be understood from git blame of that test.
I'll point out, however, that there is still a number of ways to satisfy A <: String without A being known at compile time to be a String. For one, Null and Nothing satisfy that, being at the bottom of Scala type hierarchy. Those two are explicitly disallowed at type matching. The other example is a bit more involved:
val UhOh: { type T <: String } = new { type T = String }
implicitly[UhOh.T <:< String] // satisfies type bound
implicitly[UhOh.T =:= String] // won't compile - compiler cannot prove the type equality
This is similar to some newtyping patterns, e.g. shapeless.tag
Out of all these possibilities, only one that can do anything reasonable is when A =:= String because String is the only type that can be actually checked at runtime. Oh, except when you use generic type in match - that does not work at all (not without ClassTag in scope at least) because such types are eliminated by erasure.
Final class cannot be extended.so for def maybeeq[A <: String](x: A) is not a correct syntax, since String is final, there should not have any subtype extend from String. the compiler smartly point out this issue.
Let me get straight into the problem that I faced while hanging around with type bounds.
Let's consider the following...
I created a function 'foo' like this
def foo[A,B](x:A,y:B):(A,B)=(x,y)
I invoked foo in scala worksheet, like
foo("Mars",2400)
I obtained a result like
res0: (String, Int) = (Mars,2400)
Notice the inferred types of Mars and 2400
Now I wanted to enforce that the function 'foo' accepts Integers or floats or Doubles (any type that is a subtype of AnyVal).
To enforce I wrote a code like
def fooNew[A<:B,B](x:A,y:B):(A,B)=(x,y)
The inferred types from the previous code was (String,Int) and when I invoked fooNew like
fooNew("Saturn",2400)
I was surprised to see that the compiler did let my code pass and did not raise the error instead it did give an output like
res0: (String, Any) = (Saturn,2400)
Now, the desired way of enforcing did not work here. Had I done something like this
def fooNew[A<:B,B<:AnyVal](x:A,y:B):(A,B)=(x,y)
The compiler would have surely raised an error for me and it did!
Error:(2, 2) inferred type arguments [String,Any] do not conform to method fooNew's type parameter bounds [A <: B,B <: AnyVal]
fooNew("Saturn",2400);}
I want to ask, why didn't the compiler the type as Int instead it inferred the type Any and let my code pass the type checks? Do I always need to enforce the second type to be a subtype of AnyVal instead of letting the compiler infer it for me? or is it a bug in the compiler. Seek pardon if you found my question misleading or not upto your expectations.
Currently I am using scala-library 2.11.8
Thankyou
def fooNew[A<:B,B](x:A,y:B):(A,B)=(x,y)
In the above you are declaring type parameter A to be a subtype of type parameter B. When you pass A as String and B as Int, the compiler goes up the class hierarchy to find a suitable type for B such that Int is a B and also String is a subtype of B. The only type in the heirarchy which satisfies these two conditions is the Any type. So, String is a subtype of Any and Int is of type Any
You can think of using your original declaration with inferred types as "find A and B such that x has type A, y has type B, and A is a subtype of B". Since A = String and B = Any satisfy these conditions, the compiler correctly infers them (there are also other solutions, e.g. A = B = Any, but this one is the most specific).
But you can change the declaration to tell the compiler "find A and B such that x has type A and y has type B, and then check that A is a subtype of B". This is done as follows:
def fooNew[A,B](x:A,y:B)(implicit evidence: A <:< B): (A,B)=(x,y)
This works because the compiler will only use the first parameter list to infer A and B. Search for "generalized type constraints" to find more information about <:< and =:=.
It seems I don't understand something important, maybe about erasure (damn it).
I have a method, which I wanted to create array of size n filled with values from gen:
def testArray[T](n: Int, gen: =>T) {
val arr = Array.fill(n)(gen)
...
}
And use it, for example as:
testArray(10, util.Random.nextInt(10))
But I get error:
scala: could not find implicit value for evidence parameter of type scala.reflect.ClassManifest[T]
val arr = Array.fill(n)(gen)
^
Please, explain what I did wrong, why this error, and what kind of code it makes impossible?
That is because in testArray the concrete type of T is not known at compile time. Your signature has to look like def testArray[T : ClassManifest](n: Int, gen: =>T), this will add an implicit parameter of type ClassManifest[T] to your method, that is automatically passed to the call of testArray and then further passed to the Array.fill call. This is called a context bound.
The Array.fill method has the following signature:
def fill[T](n: Int)(elem: => T)(implicit arg0: ClassManifest[T]): Array[T]
In order to get an instance of ClassManifest[T] you need to know the concrete type. A ClassManifest can be obtained like this:
implicitly[ClassManifest[String]]
A ClassManifest is implicitly available for every concrete type.
For any implicit error, you can add the implicits you require to the method with the type parameter:
def wrap[T](n:Int)(elem: => T)(implicit c:ClassManifest[T], o:Ordering[T])
If you did not yourself introduce ClassManifest or Ordering, the writers of the library have (most likely) provided sensible defaults for you.
If you would call the wrap method:
wrap(2)(3)
It's expanded like this:
wrap[Int](2)(3)(implicitly[ClassManifest[Int]], implicitly[Ordering[Int]])
If you introduced a custom class Person here, you would get an error for not finding an implicit instance of Ordering[Person]. The writers of the library could not have known how to order Person. You could solve that like this:
class Person
implicit val o = new Ordering[Person] { // implement required methods }
wrap(2)(new Person)
The Scala compiler looks in different scopes for implicits, an Ordering would usually not be specified like this. I suggest you look up implicit resolution on the internet to learn more about it.
I'd like to know how do the member types work in Scala, and how should I associate types.
One approach is to make the associated type a type parameter. The advantages of this approach is that I can prescribe the variance of the type, and I can be sure that a subtype doesn't change the type. The disadvantages are, that I cannot infer the type parameter from the type in a function.
The second approach is to make the associated type a member of the second type, which has the problem that I can't prescribe bounds on the subtypes' associated types and therefore, I can't use the type in function parameters (when x : X, X#T might not be in any relation with x.T)
A concrete example would be:
I have a trait for DFAs (could be without the type parameter)
trait DFA[S] { /* S is the type of the symbols in the alphabet */
trait State { def next(x : S); }
/* final type Sigma = S */
}
and I want to create a function for running this DFA over an input sequence, and I want
the function must take anything <% Seq[alphabet-type-of-the-dfa] as input sequence type
the function caller needn't specify the type parameters, all must be inferred
I'd like the function to be called with the concrete DFA type (but if there is a solution where the function would not have a type parameter for the DFA, it's OK)
the alphabet types must be unconstrained (ie. there must be a DFA for Char as well as for a yet unknown user-defined class)
the DFAs with different alphabet types are not subtypes
I tried this:
def runDFA[S, D <: DFA[S], SQ <% Seq[S]](d : D)(seq : SQ) = ....
this works, except the type S is not inferred here, so I have to write the whole type parameter list on each call site.
def runDFA[D <: DFA[S] forSome { type S }, SQ <% Seq[D#Sigma]]( ... same as above
this didn't work (invalid circular reference to type D??? (what is it?))
I also deleted the type parameter, created an abstract type Sigma and tried binding that type in the concrete classes. runDFA would look like
def runDFA[D <: DFA, SQ <% Seq[D#Sigma]]( ... same as above
but this inevitably runs into problems like "type mismatch: expected dfa.Sigma, got D#Sigma"
Any ideas? Pointers?
Edit:
As the answers indicate there is no simple way of doing this, could somebody elaborate more on why is it impossible and what would have to be changed so it worked?
The reasons I want runDFA ro be a free function (not a method) is that I want other similar functions, like automaton minimization, regular language operations, NFA-to-DFA conversions, language factorization etc. and having all of this inside one class is just against almost any principle of OO design.
First off, you don't need the parameterisation SQ <% Seq[S]. Write the method parameter as Seq[S]. If SQ <% Seq[S] then any instance of it is implicitly convertable to Seq[S] (that's what <% means), so when passed as Seq[S] the compiler will automatically insert the conversion.
Additionally, what Jorge said about type parameters on D and making it a method on DFA hold. Because of the way inner classes work in Scala I would strongly advise putting runDFA on DFA. Until the path dependent typing stuff works, dealing with inner classes of some external class can be a bit of a pain.
So now you have
trait DFA[S]{
...
def runDFA(seq : Seq[S]) = ...
}
And runDFA is all of a sudden rather easy to infer type parameters for: It doesn't have any.
Scala's type inference sometimes leaves much to be desired.
Is there any reason why you can't have the method inside your DFA trait?
def run[SQ <% Seq[S]](seq: SQ)
If you don't need the D param later, you can also try defining your method without it:
def runDFA[S, SQ <% Seq[S]](d: DFA[S])(seq: SQ) = ...
Some useful info on how the two differs :
From the the shapeless guide:
Without type parameters you cannot make dependent types , for example
trait Generic[A] {
type Repr
def to(value: A): Repr
def from(value: Repr): A
}
import shapeless.Generic
def getRepr[A](value: A)(implicit gen: Generic[A]) =
gen.to(value)
Here the type returned by to depends on the input type A (because the supplied implicit depends on A):
case class Vec(x: Int, y: Int)
case class Rect(origin: Vec, size: Vec)
getRepr(Vec(1, 2))
// res1: shapeless.::[Int,shapeless.::[Int,shapeless.HNil]] = 1 :: 2 ::
HNil
getRepr(Rect(Vec(0, 0), Vec(5, 5)))
// res2: shapeless.::[Vec,shapeless.::[Vec,shapeless.HNil]] = Vec(0,0)
:: Vec(5,5) :: HNil
without type members this would be impossible :
trait Generic2[A, Repr]
def getRepr2[A, R](value: A)(implicit generic: Generic2[A, R]): R =
???
We would have had to pass the desired value of Repr to getRepr as a
type parameter, effec vely making getRepr useless. The intui ve
take-away from this is that type parameters are useful as “inputs” and
type members are useful as “outputs”.
please see the shapeless guide for details.