def combine[ T ]( s: Seq[ Stream[ T ] ] ): Stream[ Seq[ T ] ] = s.map( _.head ) #:: combine( s.map( _.tail ) )
val s13 = combine( s1, s6 )
val s13: Stream[Seq[AnyVal]]
val s1: Stream[Int]
val s6: Stream[Double]
Hi Hugo,I suspect what you want may be impossible. When you say "the types" must be the same, I guess you could either mean1. the most specific types, or2. the types that would be inferred during typechecking.If you mean (1), this would be bad, because the most specific type of, for example, Stream.continually(x) may actually be Stream[x.type] or some other refinement that you could imagine (for classes with type members, you could come up with lots of refinements that make their types more specific). This becomes both difficult to decide for the compiler and difficult to understand as a programmer—surely there would be some bad results.If you mean (2), then I'm not sure how that would work, because the types inferred for the arguments during typechecking depend on the types that are expected in that context. So there's a kind of circularity there.At the end of the day, your two streams do have the same type: Stream[AnyVal]. They just happen to each have some other types too...
Anyway, my comment on (2) was apparently a joke because we do have a way of doing this: implicit search. Indeed, none of the theoretical mumbo jumbo matters when you have implicit search just absolutely wrecking the place. Something like this might suit you:scala> implicit class StreamCombine[A](val s: Stream[A]) extends AnyVal {
| def combine(other: Stream[A]): Stream[A] = if(s.isEmpty) other else s.head #:: other.combine(s.tail)
| }
defined class StreamCombine
scala> Stream(1).combine(Stream(1.0))
<console>:14: error: type mismatch;
found : Double(1.0)
required: Int
Stream(1).combine(Stream(1.0))
^
scala> Stream(1).combine(Stream(2))
res3: Stream[Int] = Stream(1, ?)Hope that helps.
def combine[ T, T1 <: T, T2 <: T ]( s1: Stream[ T1 ], s2: Stream[ T2 ] )( implicit ev: T1 =:= T2 ): Stream[ Seq[ T ] ] = combine( Array( s1, s2 ) )
val s1: Stream[Int]
val s6: Stream[Double]
val s13 = combine( s1, s6 )
Multiple markers at this line:
- not enough arguments for method combine: (implicit ev:
=:=[Int,Double])Stream[Seq[AnyVal]]. Unspecified value parameter ev.
- Cannot prove that Int =:= Double.
Hi,The combine function you show doesn't really match with the rest of your mail, so that makes it a bit difficult to help (and all the spaces make it a bit difficult to read too...).But let's assume that your combine function looks like this:def combine[T](s1: Stream[T], s2: Stream[T]): Stream[Seq[T]] = ???
def combine[T](s:Seq[Stream[T]]): Stream[Seq[T]] = ???
Now you indeed have the issue that type T is inferred based on both s1 and s2. If they have different types, T will be inferred to be the least upper bound of both.What you can do is put s1 and s2 in separate parameter lists. Then T will be inferred based only on the first parameter list.def combine[T](s1: Stream[T])(s2: Stream[T]): Stream[Seq[T]] = ???
Take a look at the following REPL transcript:scala> def combine1[T](s1: Stream[T], s2: Stream[T]): Stream[Seq[T]] = ???combine1: [T](s1: Stream[T], s2: Stream[T])Stream[Seq[T]]scala> def combine2[T](s1: Stream[T])(s2: Stream[T]): Stream[Seq[T]] = ???combine2: [T](s1: Stream[T])(s2: Stream[T])Stream[Seq[T]]scala> combine1(Stream.empty[Int], Stream.empty[Double]) // this compilesscala.NotImplementedError: an implementation is missingat scala.Predef$.$qmark$qmark$qmark(Predef.scala:284)at .combine1(<console>:11)... 37 elidedscala> combine2(Stream.empty[Int])(Stream.empty[Double]) // this doesn't compile<console>:13: error: type mismatch;found : scala.collection.immutable.Stream[Double]required: Stream[Int]combine2(Stream.empty[Int])(Stream.empty[Double])^
scala> class A
defined class A
scala> class B extends A
defined class B
scala> class C
defined class C
scala> val a = new A
a: A = A@3889c343
scala> val b = new B
b: B = B@7a6e0f3c
scala> val c = new C
c: C = C@6ac0fd1d
scala> def c1[T](a: T, b: T): (T, T) = (a, b)
c1: [T](a: T, b: T)(T, T)
scala> c1(a, b)
res3: (A, A) = (A@3889c343,B@7a6e0f3c)
scala> c1(a, c)
res4: (Object, Object) = (A@3889c343,C@6ac0fd1d)
scala> def c2[T, U](a: T, b: U)(implicit ev: U <:< T): (T, U) = (a, b)
c2: [T, U](a: T, b: U)(implicit ev: <:<[U,T])(T, U)
scala> c2(a, b)
res6: (A, B) = (A@3889c343,B@7a6e0f3c)
scala> c2(a, c)
<console>:48: error: Cannot prove that C <:< A.
c2(a, c)
--
You received this message because you are subscribed to the Google Groups "scala-user" group.
To unsubscribe from this group and stop receiving emails from it, send an email to scala-user+unsubscribe@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
So I realize that what I want (need?) is to ensure that a Seq[T] (in the initial example I use a list to hold the streams)
have the same most specific type - which is case (1). So if I understand you correctly, this is impossible to enforce.
As for your example, I confess I don't quite get it. If I had a sequence of streams, how could I use that technique?
Also, I don't see how that works if you have streams with various elements. The code seems to return either one or the other.
I will have too look at this more carefully.
To unsubscribe from this group and stop receiving emails from it, send an email to scala-user+...@googlegroups.com.
Hugo,So I realize that what I want (need?) is to ensure that a Seq[T] (in the initial example I use a list to hold the streams)have the same most specific type - which is case (1). So if I understand you correctly, this is impossible to enforce....> This may not be helpful to solve what I have, which really seems to be: ensuring that a Seq[T]uses only a single type T and not its LUB.
Yes, essentially my point (1) was that there is actually no difference between using a single type T and the LUB of the elements of the stream, or if there was, it wouldn't be what you want: for example, Seq(1.0, 2.0) could be rejected because the singleton types Double(1.0) and Double(2.0) don't agree.
As for your example, I confess I don't quite get it. If I had a sequence of streams, how could I use that technique?
Also, I don't see how that works if you have streams with various elements. The code seems to return either one or the other.
I will have too look at this more carefully.I'm not exactly sure what you mean by "various elements."
If you look closely at the function I wrote, it implements a special case of your combine from the OP where you only want to combine two streams—and it just interleaves their elements. (Actually, your function will throw an error when it encounters the end of a stream, so they're not quite the same.)
But yes, it's not clear to me how to generalize this to an arbitrary stream. It's definitely the case that if you get, for example, a Stream[AnyVal] from elsewhere, there is no way of enforcing with the type system that all of its elements are, say, of type Int, because that information is lost. In fact, it's not even possible to write a function to do that at runtime and always terminate.
More broadly speaking, I suggest you reconsider whether what you're trying to accomplish is necessary at all. When the typechecker takes a really high LUB like AnyVal or Any, usually it causes type errors immediately when you try to use the stream again—so you'll pretty much always catch the unwanted behavior at compile time.
On the other hand, you might end up in situations where you do want a Seq of Streams of LUBs of the types in question. Suppose you want to construct a Seq of Streams of Options and do something like Seq(Stream(None), Stream(Some(5), ...), ...). It's quite desirable for the typechecker to take the LUB and not yell at you about Some[Int] not being a subtype of None.type. (Indeed, I often end up up-casting None or replacing it with another expression to avoid this kind of thing, because the typechecker isn't aggressive enough to catch all of these cases.)
If excluding Any, AnyVal and AnyRef is enough for you, you can use something like this toy project of me.
import implicitlogic._def combine[T](s: Seq[Stream[T]])(implicit ev: Not[(AnyVal <:< T) Or (AnyRef <:< T)]): Stream[Seq[T]] = ???