1

Is it possible to add elements to some mutable object which should be a heterogeneous list?

So what I mean, I am dealing with Dijkstra's algorithm, and i need to keep some functions in arcs of the graph in such a way:

class Arc[M, N, T, K](var start: Node[M], var end: Node[N], var f: T => K)

Where start - is a start node; end - end node; f - is some function between nodes and the Arc is an object to keep this function, and it's the most important thing for me.

It is all perfect, but I keep all arcs in a list inside node:

class Node[T] (s: T) (implicit m: TypeTag[T]) {
    var transitions: List[Arc[T, _, _, _]] = Nil
    //...
    def addArc[M, N, L] (end: Node[M], f: N => L): Arc[T, _, _, _] = {
        transitions = new Arc(this, end, f) :: transitions
        transitions.head
    }
}

And u see, the problem is that we r losing types in simple lists; And while adding new arcs to our node we gonna lose exactly all information about types.

The possible way to dicide the problem is to use HLists; example of some working code (to add more information to the exaplnation):

// for example we got some type convertion functions
def doubleToInt(x: Double) = x.toInt
def doubleToString(x: Double) = x.toString
def stringToInt(x: String) = x.toInt
def intToDouble(x: Int) = x.toDouble  

// and we got some class, with two any args and one function; 
class testyfunc[M, N, K, T] (a: M, b: N, c: K => T) {
  var f: K => T = c(_)
}

// ok lets build HList
var omglist = HNil
var omglist1 = (new testyfunc (1, "234", intToDouble)) :: omglist
var omglist2 = (new testyfunc (1, "234", doubleToInt)) :: omglist1
var omglist3 = (new testyfunc (1, "234", doubleToString)) :: omglist2
var omglist4 = (new testyfunc (1, "234", stringToInt)) :: omglist3

// it all works!
println(omglist4.head.f("223")) // > 223

// lest check types; yeah it's perfect!
/* shapeless.::[main.scala.Main.testyfunc[Int,java.lang.String,String,Int],
   shapeless.::[main.scala.Main.testyfunc[Int,java.lang.String,Double,java.lang.String],
   shapeless.::[main.scala.Main.testyfunc[Int,java.lang.String,Double,Int],
   shapeless.::[main.scala.Main.testyfunc[Int,java.lang.String,Int,Double],
   shapeless.HNil]]]] */

by the way, now it's all in a such way:

var omglistNH: List[testyfunc[_, _, _, _]] = Nil // here we loose types!
omglistNH = (new testyfunc (1, "234", intToDouble)) :: omglistNH
omglistNH = (new testyfunc (1, "234", doubleToInt)) :: omglistNH
omglistNH = (new testyfunc (1, "234", doubleToString)) :: omglistNH
omglistNH = (new testyfunc (1, "234", stringToInt)) :: omglistNH

println(omglistNH.head.f("223")) 
// obviously we got a type error; cause of incorrect types
/* type mismatch;
 found   : String("223")
 required: _$9 where type _$9
 println(omglistNH.head.f("223"))
                       ^          */

So the question is how can I make smth like the code below (it is incorrect -- type error), and to add elements to this HList:

var omglist = HNil
omglist = (new testyfunc (1, "234", intToDouble)) :: omglist
omglist = (new testyfunc (1, "234", doubleToInt)) :: omglist
omglist = (new testyfunc (1, "234", doubleToString)) :: omglist
omglist = (new testyfunc (1, "234", stringToInt)) :: omglist

cause I even got no idea how to pass this type mismatching, and I see no ways to keep all transitions as a field of a node with keeping all types.

EDIT

hm, mb I can pass the transitions into constructor and not to use mutable objects at all.

DaunnC
  • 1,301
  • 15
  • 30

0 Answers0