I've been trying to figure out why the following code is ambiguous...
public func product <T1: Sequence, T2: Sequence> (_ sequence1: T1, _ sequence2: T2) ->
AnySequence<(T1.Element, T2.Element)> {
return AnySequence(
sequence1.flatMap { element1 in
sequence2.map { element2 in
(element1, element2)
}
}
)
}
public func product <T1: LazySequenceProtocol, T2: LazySequenceProtocol> (_ sequence1: T1, _ sequence2: T2) ->
LazySequence<AnySequence<(T1.Element, T2.Element)>> {
return AnySequence(
sequence1.flatMap { element1 in
sequence2.map { element2 in
(element1, element2)
}
}
).lazy
}
...when I call it with two lazy sequences and a call to makeIteratorEXAMPLE.
_ = product([1, 2].lazy, [3, 4].lazy).makeIterator()
Yet, the following code doesn't have this ambiguity...
public struct Product2Sequence <T1: Sequence, T2: Sequence>: Sequence {
public typealias Element = (T1.Element, T2.Element)
public typealias Iterator = AnyIterator<Element>
private let iterator: Iterator
internal init (_ sequence1: T1, _ sequence2: T2) {
self.iterator = AnyIterator(
sequence1.flatMap { element1 in
sequence2.map { element2 in
(element1, element2)
}
}.makeIterator()
)
}
public func makeIterator () -> Iterator {
return self.iterator
}
}
public struct LazyProduct2Sequence <T1: LazySequenceProtocol, T2: LazySequenceProtocol>: LazySequenceProtocol {
public typealias Element = (T1.Element, T2.Element)
public typealias Iterator = AnyIterator<Element>
private let iterator: Iterator
internal init (_ sequence1: T1, _ sequence2: T2) {
self.iterator = AnyIterator(
sequence1.flatMap { element1 in
sequence2.map { element2 in
(element1, element2)
}
}.makeIterator()
)
}
public func makeIterator () -> Iterator {
return self.iterator
}
}
public func product <T1: Sequence, T2: Sequence> (_ sequence1: T1, _ sequence2: T2) -> Product2Sequence<T1, T2> {
return Product2Sequence(sequence1, sequence2)
}
public func product <T1: LazySequenceProtocol, T2: LazySequenceProtocol> (_ sequence1: T1, _ sequence2: T2) ->
LazyProduct2Sequence<T1, T2> {
return LazyProduct2Sequence(sequence1, sequence2)
}
...when I call it with two lazy sequences and a call to makeIteratorEXAMPLE.
_ = product([1, 2].lazy, [3, 4].lazy).makeIterator()
My reasoning is that a lazy sequence conforms both to LazySequenceProtocol and Sequence so the type system doesn't know which product to choose. But by that definition the second version should also not work.
I'm using Swift 4.0.
What makes the second version work?