I’d like to implement a “matrix dot product” in Scala in the following way:
type Real = Double
type Row = Array[Real]
type Matrix = Array[Row]
def dot[T](f: (T,T) => Real)(as: Iterable[T], bs: Iterable[T]): Real =
(for ((a, b) <- as zip bs) yield f(a, b)) sum
def rowDot(r1: Row, r2: Row) = dot(_*_)(r1, r2)
def matDot(m1: Matrix, m2: Matrix) = dot(rowDot)(m1, m2)
However, the definition of rowDot doesn’t work. Scala needs explicit type annotations for the anonymous function (_*_), so instead I must write
def rowDot(r1: Row, r2: Row) = dot((x:Real, y: Real) => x*y)(r1, r2)
or
def rowDot = dot((x:Real, y: Real) => x*y) _
Is there some way to change the definition of dot so that the shorthand (_*_) can be used?
Edit: Another confusion: matDot also gives type errors in certain circumstances. It fails with Arrays of Arrays, but not with Lists of Arrays
scala> matDot(Array(Array(1.0,2.0)), Array(Array(1.0,2.0,3.0)))
<console>:27: error: type mismatch;
found : Array[Array[Double]]
required: Iterable[Iterable[Real]]
matDot(Array(Array(1.0,2.0)), Array(Array(1.0,2.0,3.0)))
^
scala> matDot(List(Array(1.0,2.0)), List(Array(1.0,2.0,3.0)))
res135: Real = 5.0
What’s the difference?
specifying
dot[Real]explicitly should work too.EDIT
replying to your edit: I think the issue is that the implicit conversion from
ArraytoWrappedArrayis not applied recursively when you have aArray[Array].Array[Int]is not anIterable[Int]; normally, when you assign it to a Iterable, anArray[Int]is implicitly converted to aWrappedArray[Int](whereWrappedArrayis a Iterable[Int]). This is what happens when you useList[Array[Int]](you get aList[WrappedArray[Int]]implicitly).However, as I said, the implicit conversion is not applied recursively, so an
Array[Array[Int]]is not implicitly converted toWrappedArray[WrappedArray[Int]].Here’s a REPL session that demonstrates the problem:
A List[Array[Int]] can be assigned to Iterable[Iterable[Int]] (note that Array is converted to WrappedArray)
An Array[Array[Int]] does not work automatically (as you discovered)
However, with some hand-holding (converting manually the inner Arrays to WrappedArrays) everything works again: