假设x和y属于同一类型,可以是Boolean
,Int
或Double
。这是我想写的函数:
f(x, y) =
- if x == Boolean ==> !x
- if x == Integer or x == Double ==> x+ y
这样做的一种方法可以是以下方法。我想知道是否有人对此有更好的想法。
def fun[T](x: T, y: T): T {
x match {
case xP: Boolean => !xP
case xP: Double => y match { case yP: Double => xP + yP }
case xP: Int => y match { case yP: Int => xP + yP }
}
}
我对此不满意的原因是x
和y
具有相同的类型。我不应该需要两个match-case
;对?
另外两件事:
[T <: Int, Double, Boolean]
是否足以将类型限制为仅三种类型? T
。 答案 0 :(得分:11)
这正是类型类旨在解决的问题。在你的情况下,你可以这样写:
trait Add[A] {
def apply(a: A, b: A): A
}
object Add {
implicit val booleanAdd: Add[Boolean] = new Add[Boolean] {
def apply(a: Boolean, b: Boolean): Boolean = !a
}
implicit def numericAdd[A: Numeric]: Add[A] = new Add[A] {
def apply(a: A, b: A): A = implicitly[Numeric[A]].plus(a, b)
}
}
类型Add[X]
的值描述了如何添加两个类型为X
的值。您将Add[X]
类型的隐式“实例”放在您希望能够对其执行此操作的每个类型X
的范围内。在这种情况下,我为Boolean
和任何具有scala.math.Numeric
实例的类型(标准库提供的类型类)提供了实例。如果您只想要Int
和Double
的实例,则可以简单地省略numericAdd
并编写自己的Add[Int]
和Add[Double]
实例。
你这样写fun
:
def fun[T: Add](x: T, y: T) = implicitly[Add[T]].apply(x, y)
并像这样使用它:
scala> fun(true, false)
res0: Boolean = false
scala> fun(1, 2)
res1: Int = 3
scala> fun(0.01, 1.01)
res2: Double = 1.02
这具有非常显着的优点,即在运行时不会在尚未定义操作的类型上爆炸。当您通过例如MatchError
例外时,不会使您的程序崩溃。两个字符串到fun
,你得到一个很好的编译失败:
scala> fun("a", "b")
<console>:14: error: could not find implicit value for evidence parameter of type Add[String]
fun("a", "b")
^
一般来说,“类型案例”匹配(即看起来像case x: X => ...
的匹配)在Scala中是一个坏主意,而且几乎总有一个更好的解决方案。通常它会涉及类型类。
答案 1 :(得分:4)
如果您想要一个用于求和数字的通用函数,您可以使用您想要Traceback (most recent call last):
File "./test1.py", line 60, in <module>
concated = tf.concat(1, [indices, tf.cast(labels,tf.int32)])
File "/Users/username/tensorflow/lib/python2.7/site-packages/tensorflow/python/ops/array_ops.py", line 309, in concat
name=name)
File "/Users/username/tensorflow/lib/python2.7/site-packages/tensorflow/python/ops/gen_array_ops.py", line 70, in _concat
name=name)
File "/Users/username/tensorflow/lib/python2.7/site-packages/tensorflow/python/ops/op_def_library.py", line 664, in apply_op
op_def=op_def)
File "/Users/username/tensorflow/lib/python2.7/site-packages/tensorflow/python/framework/ops.py", line 1836, in create_op
set_shapes_for_outputs(ret)
File "/Users/username/tensorflow/lib/python2.7/site-packages/tensorflow/python/framework/ops.py", line 1476, in set_shapes_for_outputs
shapes = shape_func(op)
File "/Users/username/tensorflow/lib/python2.7/site-packages/tensorflow/python/ops/array_ops.py", line 364, in _ConcatShape
concat_dim + 1:].merge_with(value_shape[concat_dim + 1:])
File "/Users/username/tensorflow/lib/python2.7/site-packages/tensorflow/python/framework/tensor_shape.py", line 527, in merge_with
self.assert_same_rank(other)
File "/Users/username/tensorflow/lib/python2.7/site-packages/tensorflow/python/framework/tensor_shape.py", line 570, in assert_same_rank
"Shapes %s and %s must have the same rank" % (self, other))
ValueError: Shapes TensorShape([]) and TensorShape([Dimension(10)]) must have the same rank
的数字进行隐式转换的特征Summable[A]
。这些转换可以是隐式方法,也可以是隐式对象中的方法,后面的内容如下所示。
Summable
这称为类型类模式。我包含了布尔情况,因为你要求它,但我坚信它在一个对元素求和的函数中没有位置。遵循的一条不错的规则是让每个函数只做一件事和一件事。然后,您可以轻松地将它们组合成更大的功能。反转布尔值在对其参数求和的函数中没有位置。
答案 2 :(得分:-1)
首先,您的示例在语法上是错误的(case
中缺少match
)。我现在可以想到的一种简单而简短的方法是这样的:
def fun[T <: AnyVal](x: T, y: T) = {
x match {
case xP: Boolean => !xP
case xP: Double => xP + y.asInstanceOf[Double]
case xP: Int => xP + y.asInstanceOf[Int]
}
}
fun(1, 2) // res0: AnyVal = 3
fun(2.5, 2.6) // res1: AnyVal = 5.1
fun(true, false) // res2: AnyVal = false