- About Scala
- Documentation
- Code Examples
- Software
- Scala Developers
scare-quoted "type-safe" contains method for covariant collections
Fri, 2012-02-10, 23:07
class MyCovariantCollection[+T, +CC[X] <: Seq[X]](xs: CC[T]) { // Oops, our "evidence" seems to be useless, as what we want // to know is that T1 <:< T, but of course we can't do that because
// of the variance position. def contains[T1](x: T1)(implicit ev: T <:< T1): Boolean = xs contains x}
// But wait! Unspecified implementation vagaries to the rescue! object Test extends App { val xs = new MyCovariantCollection(List(1, 2, 3)) assert(xs contains "abc", "I'm sure it's in there somewhere")}
// Thank-you type inference algorithm! Pick the most specific// type while resolving the first parameter list without regard// for the fact that we are doomed once you see the second // parameter list. That's what we want today.% scalac ./covariance-contains.scala ./covariance-contains.scala:11: error: Cannot prove that Int <:< java.lang.String. assert(xs contains "abc", "I'm sure it's in there somewhere") ^one error found
/*Yes, of course this works:
xs.contains[Any]("abc")
I don't know about you guys but people going that far out of their way to look for Strings in a list of Ints is not my most pressing concern.*/
// But wait! Unspecified implementation vagaries to the rescue! object Test extends App { val xs = new MyCovariantCollection(List(1, 2, 3)) assert(xs contains "abc", "I'm sure it's in there somewhere")}
// Thank-you type inference algorithm! Pick the most specific// type while resolving the first parameter list without regard// for the fact that we are doomed once you see the second // parameter list. That's what we want today.% scalac ./covariance-contains.scala ./covariance-contains.scala:11: error: Cannot prove that Int <:< java.lang.String. assert(xs contains "abc", "I'm sure it's in there somewhere") ^one error found
/*Yes, of course this works:
xs.contains[Any]("abc")
I don't know about you guys but people going that far out of their way to look for Strings in a list of Ints is not my most pressing concern.*/
Sat, 2012-02-11, 10:31
#2
Re: scare-quoted "type-safe" contains method for covariant coll
On Fri, Feb 10, 2012 at 10:07 PM, Paul Phillips wrote:
> class MyCovariantCollection[+T, +CC[X] <: Seq[X]](xs: CC[T]) {
> // Oops, our "evidence" seems to be useless, as what we want
> // to know is that T1 <:< T, but of course we can't do that because
> // of the variance position.
> def contains[T1](x: T1)(implicit ev: T <:< T1): Boolean = xs contains x
> }
>
> // But wait! Unspecified implementation vagaries to the rescue!
> object Test extends App {
> val xs = new MyCovariantCollection(List(1, 2, 3))
> assert(xs contains "abc", "I'm sure it's in there somewhere")
> }
>
> // Thank-you type inference algorithm! Pick the most specific
> // type while resolving the first parameter list without regard
> // for the fact that we are doomed once you see the second
> // parameter list. That's what we want today.
> % scalac ./covariance-contains.scala
> ./covariance-contains.scala:11: error: Cannot prove that Int <:<
> java.lang.String.
> assert(xs contains "abc", "I'm sure it's in there somewhere")
> ^
> one error found
>
> /*
> Yes, of course this works:
>
> xs.contains[Any]("abc")
>
> I don't know about you guys but people going that far out of their way
> to look for Strings in a list of Ints is not my most pressing concern.
> */
Maybe I'm being a bit dim, but why is this preferable to just pimping
away the variance altogether?
scala> :paste
// Entering paste mode (ctrl-D to finish)
class InvariantContains[T, CC[X] <: Seq[X]](xs: CC[T]) {
def invarContains(x : T) : Boolean = xs contains x
}
// Exiting paste mode, now interpreting.
defined class InvariantContains
scala> implicit def invar[T, CC[X] <: Seq[X]](xs: CC[T]) = new
InvariantContains(xs)
invar: [T, CC[X] <: Seq[X]](xs: CC[T])InvariantContains[T,CC]
scala> List(1, 2, 3) invarContains "foo"
:10: error: type mismatch;
found : java.lang.String("foo")
required: Int
List(1, 2, 3) invarContains "foo"
^
Cheers,
Miles
Sat, 2012-02-11, 16:01
#3
Re: scare-quoted "type-safe" contains method for covariant coll
On Sat, Feb 11, 2012 at 1:28 AM, Miles Sabin <miles@milessabin.com> wrote:
Maybe I'm being a bit dim, but why is this preferable to just pimping
away the variance altogether?
It's interesting because it's possible to do it without an intermediate structure (which is surprising) not because it's appealing.
That said, it might be cheaper (but I'm not sure.)
Sat, 2012-02-11, 16:41
#4
Re: scare-quoted "type-safe" contains method for covariant coll
On Sat, Feb 11, 2012 at 2:52 PM, Paul Phillips wrote:
> On Sat, Feb 11, 2012 at 1:28 AM, Miles Sabin wrote:
>>
>> Maybe I'm being a bit dim, but why is this preferable to just pimping
>> away the variance altogether?
>
>
> It's interesting because it's possible to do it without an intermediate
> structure (which is surprising) not because it's appealing.
Oh, so the idea would be to replace the existing definition of
contains with your one with the type constraint, rather than use that
MyConvariantCollection type (which looks a lot like an intermediate
structure to me)? In which case my only quibble would be that using
=:= rather than <:< would have the same effect and be a bit more
transparent.
Cheers,
Miles
Sat, 2012-02-11, 17:41
#5
Re: scare-quoted "type-safe" contains method for covariant coll
On Sat, Feb 11, 2012 at 7:38 AM, Miles Sabin <miles@milessabin.com> wrote:
In which case my only quibble would be that using
=:= rather than <:< would have the same effect and be a bit more
transparent.
You can't, for the same reason you can't reverse the operands. (Except instead of "covariant type in contravariant position" you have "covariant type in invariant position".)
Sat, 2012-02-11, 17:51
#6
Re: scare-quoted "type-safe" contains method for covariant coll
On Sat, Feb 11, 2012 at 7:38 AM, Miles Sabin <miles@milessabin.com> wrote:
rather than use that
MyConvariantCollection type (which looks a lot like an intermediate
structure to me)?
Yes, "MyCovariantCollection" was supposed to be read as "List".
Sat, 2012-02-11, 19:31
#7
Re: scare-quoted "type-safe" contains method for covariant coll
What will the value of the implicit parameter be? Won't it be a new instance of an identity function?
Chris
On 11 Feb 2012, at 14:52, Paul Phillips <paulp@improving.org> wrote:
Chris
On 11 Feb 2012, at 14:52, Paul Phillips <paulp@improving.org> wrote:
On Sat, Feb 11, 2012 at 1:28 AM, Miles Sabin <miles@milessabin.com> wrote:Maybe I'm being a bit dim, but why is this preferable to just pimping
away the variance altogether?
It's interesting because it's possible to do it without an intermediate structure (which is surprising) not because it's appealing.
That said, it might be cheaper (but I'm not sure.)
Sat, 2012-02-11, 19:41
#8
Re: scare-quoted "type-safe" contains method for covariant coll
On Sat, Feb 11, 2012 at 10:21 AM, Chris Marshall <oxbowlakes@gmail.com> wrote:
What will the value of the implicit parameter be? Won't it be a new instance of an identity function?
There is only one instance.
private[this] final val singleton_<:< = new <:<[Any,Any] { def apply(x: Any): Any = x } implicit def conforms[A]: A <:< A = singleton_<:<.asInstanceOf[A <:< A]
There's a lot of merit on this just in the decreased noise level from
the detractors. Granted, they'll pick up on something else if they are
bull-headed enough, but _some_ of them are bound not to be bull-headed
enough! :-)
On Fri, Feb 10, 2012 at 20:07, Paul Phillips wrote:
> class MyCovariantCollection[+T, +CC[X] <: Seq[X]](xs: CC[T]) {
> // Oops, our "evidence" seems to be useless, as what we want
> // to know is that T1 <:< T, but of course we can't do that because
> // of the variance position.
> def contains[T1](x: T1)(implicit ev: T <:< T1): Boolean = xs contains x
> }
>
> // But wait! Unspecified implementation vagaries to the rescue!
> object Test extends App {
> val xs = new MyCovariantCollection(List(1, 2, 3))
> assert(xs contains "abc", "I'm sure it's in there somewhere")
> }
>
> // Thank-you type inference algorithm! Pick the most specific
> // type while resolving the first parameter list without regard
> // for the fact that we are doomed once you see the second
> // parameter list. That's what we want today.
> % scalac ./covariance-contains.scala
> ./covariance-contains.scala:11: error: Cannot prove that Int <:<
> java.lang.String.
> assert(xs contains "abc", "I'm sure it's in there somewhere")
> ^
> one error found
>
> /*
> Yes, of course this works:
>
> xs.contains[Any]("abc")
>
> I don't know about you guys but people going that far out of their way
> to look for Strings in a list of Ints is not my most pressing concern.
> */
>