// RUN: not %target-swift-frontend %s -typecheck /// Abstraction of numeric types that approximate real numbers protocol ApproximateReal { init() // zero func * (Self,Self) -> Self func + (Self,Self) -> Self func / (Self,Self) -> Self func - (Self,Self) -> Self prefix func + (Self) -> Self prefix func - (Self) -> Self } extension Double : ApproximateReal {} extension Float : ApproximateReal {} // Abstraction of a mathematical vector protocol Vector { init() associatedtype Element : ApproximateReal func dotProduct(Self) -> Element // Extras var count: Int {get} subscript(Int) -> Element {get set} associatedtype Tail } struct EmptyVector : Vector { init() {} typealias Element = T func dotProduct(other: EmptyVector) -> Element { return Element() // zero } var count: Int { return 0 } subscript(i: Int) -> Element { get { fatalError("subscript out-of-range") } set { fatalError("subscript out-of-range") } } } struct Vector : Vector { typealias Element = Tail.Element init(head: Element, tail: Tail) { self.head = head self.tail = tail } init() { self.head = Element() self.tail = Tail() } /* init(scalar: Element) { self.head = Element() self.tail = Tail() } */ func dotProduct(other: Vector) -> Element { return head * other.head + tail.dotProduct(other.tail) } var count: Int { return tail.count + 1 } var head: Element var tail: Tail subscript(i: Int) -> Element { get { return i == 0 ? head : tail[i - 1] } set { if i == 0 { head = newValue } else { tail[i - 1] = newValue } } } } extension Vector where Tail == EmptyVector { init(_ scalar: Element) { self.init() self[0] = scalar } } //===--- A nice operator for composing vectors ----------------------------===// //===--- there's probably a more appropriate symbol -----------------------===// infix operator ⋮ { associativity right precedence 1 } func ⋮ (lhs: T, rhs: T) -> Vector > > { return Vector(head: lhs, tail: Vector(head: rhs, tail: EmptyVector())) } func ⋮ (lhs: T, rhs: Vector) -> Vector > { return Vector(head: lhs, tail: rhs) } extension Vector : CustomDebugStringConvertible { var debugDescription: String { if count == 1 { return "Vector(\(String(reflecting: head)))" } return "\(String(reflecting: head)) ⋮ " + (count == 2 ? String(reflecting: self[1]) : String(reflecting: tail)) } } //===--- Test -------------------------------------------------------------===// print(Vector(head: 3.0, tail: EmptyVector())) print(3.0 ⋮ 4.0 ⋮ 5.0) print( (3.0 ⋮ 4.0 ⋮ 5.0).dotProduct(6.0 ⋮ 7.0 ⋮ 8.0) ) // 86.0 // print( (3.0 ⋮ 4.0 ⋮ 5.0).dotProduct(6.0 ⋮ 7.0) ) // Won't compile