我试图了解scala类型参数,并且在确定如何进行转换时遇到一些困难。
假设我正在建模tic-tac-toe:
sealed trait Side {
def toChar : Char
def toInt : Int
def toDouble : Double = toInt.toDouble
}//end trait Side
case object X extends Side {
override val toChar = 'X'
override val toInt = -1
}//end case object X extends Side
case object O extends Side {
override val toChar = 'O'
override val toInt = 1
}//end case object O extends Side
case object EMPTY extends Side {
override val toChar = '*'
override val toInt = 0
}
然后我以一种自然代表游戏的方式模拟一个tic tac板,也可以转换为一个对机器学习技术有用的数字数组。
class Board(val rows : Int = 3,
val cols : Int = 3,
val repr : Array[Array[Side]] = Array.ofDim[Side](3,3)) {
def flatten : Array[Side] = repr.flatten
/**
* Converts this board into a 1-D numeric array. This is likely the
* incorrect method signature.
*/
def flattenNumeric[T] : Array[T] = ???
}
我的问题是:如何替换???
?
我希望能够调用表格
val board = new Board
board.flattenNumeric[Int] //returns Array(0, 0, 0, 0, 0, 0, 0, 0, 0)
board.flattenNumeric[Double] //returns Array(0.0, 0.0, ...)
提前感谢您的协助。
答案 0 :(得分:1)
如果您只需要使用两种类型参数,我建议您只编写单独的flattenInt
和flattenDouble
方法 - 它更简单,更清晰。但是,这不是你问题的答案,所以如果你真的希望这是通用的,那么标准的Scala方法就是使用这样的type class:
class Board(val rows: Int = 3,
val cols: Int = 3,
val repr: Array[Array[Side]] = Array.ofDim[Side](3,3)) {
def flatten: Array[Side] = repr.flatten
trait FromSide[A] {
def apply(side: Side): A
}
object FromSide {
implicit object intFromSide extends FromSide[Int] {
def apply(side: Side) = side.toInt
}
implicit object doubleFromSide extends FromSide[Double] {
def apply(side: Side) = side.toDouble
}
implicit object charFromSide extends FromSide[Char] {
def apply(side: Side) = side.toChar
}
}
/**
* Converts this board into a 1-D numeric array. This is likely the
* incorrect method signature.
*/
def flattenNumeric[T: FromSide: Manifest]: Array[T] =
flatten.map(implicitly[FromSide[T]].apply)
}
现在,例如board.flattenNumeric[Int]
会编译,但flattenNumeric[String]
会赢。
请注意Manifest
部分只是因为您正在使用Array
而必需 - 如果您切换到Scala自己的收藏类型,则您不需要它。< / p>
通过使用清单或类型标记也可以做到这一点,但这是使程序成为可怕的运行时错误的快速方法。