Generically typed classes in collections in Scala

I'm having a problem with a generic class I'm creating in Scala. I have the following class:

class Channel[T, U](val endPoint : EventSource[U], val filter : Occurrence[T] => Boolean,
    val map : Occurrence[T] => Occurrence[U]) {

    def send(occurrence : Occurrence[T]) {
        if (filter(occurrence)) {
            endPoint.occur(map(occurrence))
        }
    }
}

Here a Channel[T,U] can be seen as a way of propagating an Occurrence[T] from an EventSource[T] to an EventSource[U]. The occurrence is only sent if the filter function is true and if so the occurrence is passed to map and the result of this is sent.

This class seems to compile and function correctly. My problem is that I want to attach several Channels to an EventSource[T] instance so it can propagate Occurrences to several different EventSources of different types. My confusion is basically how to do this:

class EventSource[T] {
    var List[Channel[T,U]] list = ...
}

What is U here? T is simply referenced from the type T in the EventSource that list belongs to (is a member of).

Sorry if this is a vague or confusing!

EDIT: I should have noted that I also want to be able to append to this list as in:

list = list ++ List[Channel[T, U](new Channel[T, U](endPoint, filter, map))

Is the append the real problem?

Answers


To maintain typing you really need to use the wild card _ type. This allows you to define list in such a way where you care about the U parameter of the Channel type when adding it to the list but not when sending an occurrence to all the channels in the list. The following compiles but as it stands it is rather circular. You need a sub class of channel that does something other than send it to another EventSource.

class Occurrence[T]
class Channel[T, U](val endPoint : EventSource[U], val filter : Occurrence[T] => Boolean,
    val map : Occurrence[T] => Occurrence[U]) {
    def send(occurrence : Occurrence[T]) {
        if (filter(occurrence))
            endPoint.occur(map(occurrence))
    }
}
class EventSource[T] {
  var list: List[Channel[T,_]]  = Nil
  def addChannel[U]( endPoint : EventSource[U], filter : Occurrence[T] => Boolean, map : Occurrence[T] => Occurrence[U]) {
    list = list ++ List[Channel[T, U]](new Channel[T, U](endPoint, filter, map))
  }
  def occur( occurrence : Occurrence[T] ) {
    list foreach { _.send( occurrence ) }
  }
}

If I understand your problem correctly, you could use Any:

class EventSource[T] {
  val list: List[Channel[T, Any]] = ...

EDIT: Is your code example where you use append copied? Because I noted that you're missing the types for Channel. Also, if you just want to add one element to your list you can use cons, which adds the new element at the beginning of your list:

Channel[Your, Types](your, para, meters)::list

If you for some reason absolutely want to add the new element to the end of that list, you can use :+.


Need Your Help

For developers, is it worth it to learn/use SSIS?

.net linq ssis packages etl

I'm starting to get involved in quite a bit of ETL work a my current job, and everyone seems to be pretty partial to SSIS. I'm struggling trying to do the most trivial transformations through BI s...

About UNIX Resources Network

Original, collect and organize Developers related documents, information and materials, contains jQuery, Html, CSS, MySQL, .NET, ASP.NET, SQL, objective-c, iPhone, Ruby on Rails, C, SQL Server, Ruby, Arrays, Regex, ASP.NET MVC, WPF, XML, Ajax, DataBase, and so on.