0
votes

edit Simplified the example. Added more detail.

What I'd like is to do is compose a class with a method. The class has a type parameter of the form A[B], where A and B are abstract types (generic parameters), and its methods can work with objects of types A or B, or other types composed from A or B. For example, the class might have a method that takes an A[B] type object as a parameter, and return a B type object.

This kind of pattern is extremely common in say, the C++ standard template library.

Is this possible in scala?

In my example below, within ListDoer, A is the abstract type name ListT and B the abstract typename TElement. Later, I try to provide the concrete types, ListT[TElement] = MyList[Double]

class ListDoer[ ListT[TElement] ]
{
  // Processes abstract list type.                 
  def doIt( list:ListT[TElement] ) : TElement = { list.get(0) }   // TElement not found

  // Attempt 2:
  type L=ListT[TElement]               // TElement not found
  def doIt2( list:L ) : TElement ={ list.get(0) }   // TElement not found
}

// More concrete list type
class MyList[TElement]
{
   var None: TElement = _                         
   def get(i:Int): TElement = None   // placeholder               
   def put(i:Int, value:TElement): Unit = { }
}

// MyList[Double] is the concrete list type that doIt should take as a parameter
val doer2 = new ListDoer[ MyList[Double] ]   // MyList[Double] takes no parameters, expected one

val list1 = new MyList[Double]
doer2.doIt( list1 )         // Process list1. Should return list1.get(0)   

list.get(0) is a placeholder implementation for this example.

ListDoer class should not require any external types other than those provided as type parameters. (e.g. it should not be tied to a particular implementation of a list, or interfaces specified in any particular collections library). However, the above code is going to require that ListT[ElementT] has a method: get(Int):ElementT and cause ListDoer to fail to be instantiated is this is not met.

The above code looks reasonable to me (coming from a C++ background), but fails to compile in two places:

  • scala can't see the name TElement anywhere within ListDoer. This make it hard to make methods that takes or returns a TElement

  • the ListDoer cannot be instantiated

It this kind of nested use of generics permitted in scala?

1
If you tell what problems are you facing and what you want out of this code maybe somebody will be able to help.pedrofurla
This is an extremely vague question without much in the way of a goal, making it very difficult to answer.MushinNoShin
Thanks -- have tidied the question up. More detail.user48956

1 Answers

2
votes
object XXX {

     class MyList[T] {
          var None: T = _
          def get(k: Int): T = None // placeholder               
          def put(k: Int, v: T): Unit = {}
     }

     class ListDoer[T] {

          // this defines the "wrapper" type 
          // which requires only get method to be there
          type W[T] = { def get(k: Int): T } 

          def doIt(list: W[T]): T = { 
               return null.asInstanceOf[T]
          } 
     }

     type L = Double
     val doer1 = new ListDoer[L] // L takes no parameters, expected one 
     val doer2 = new ListDoer[Double] // L takes no parameters, expected one

     val list1 = new MyList[Double]
     val list2 = List[L]()
     doer1.doIt(list1)

}