Is it possible to extend an generic class for a specialised/constructed generic type? I would like to extend Int Arrays with a method to calculate the sum of its elements.>
Managed to get something working in an extensible, generic fashion without abusing the type system too badly, however it has some limitations.
protocol Addable {
func +(lhs: Self, rhs: Self) -> Self
class var identity: Self { get }
}
extension Int : Addable {
static var identity: Int { get { return 0 } }
}
extension String : Addable {
static var identity: String { get { return "" } }
}
extension Array {
func sum() -> U? {
let s: U? = U.identity
return self.sum(s)
}
func sum(start: U?) -> U? {
return reduce(start) { lhs, rhs in
switch (lhs, rhs) {
case (.Some(let left), let right as U):
return left + right
default:
return nil
}
}
}
}
Specifically: with this solution, type inferencing won't work on the no-parameter sum()
method, so you have to either annotate the expected return type or give it a starting value (from which it can infer the type).
Note also that this returns a value of Optional type: if for any reason a sum of the expected type cannot be computed from the array, it returns nil.
To illustrate:
let int_array = Array(1...10)
let x: Int? = int_array.sum() // result: {Some 55}
let x2 = int_array.sum(0) // result: {Some 55}
let x3 = int_array.sum() // Compiler error because it can't infer type
let string_array = ["a", "b", "c"]
let y: String? = string_array.sum() // result: {Some "abc"}
let y2 = string_array.sum("") // result: {Some "abc"}
let y3: Int? = string_array.sum() // result: nil (can't cast String to Int)
let y4 = string_array.sum(0) // result: nil (can't cast String to Int)
let double_array = [1.3, 4.2, 2.1]
let z = double_array.sum(0.0) // Compiler error because we haven't extended Double to be Addable