Swift Error: 'Sequence' Requires the Types 'T' and 'Arrayslice<T>' Be Equivalent

Swift Error: 'Sequence' requires the types 'T' and 'ArraySlice T ' be equivalent

Your code compiles fine as Swift 3.1 (Xcode 8.3.3). The error

'Sequence' requires the types 'T' and 'ArraySlice<T>' be equivalent

occurs when compiling as Swift 4 (Xcode 9, currently beta), because then
the Sequence protocol already defines the

associatedtype Element where Self.Element == Self.Iterator.Element

which conflicts with your definition. You can either choose a different
name for your type alias, or just remove it (and use T instead):

public struct Matrix<T> where T: FloatingPoint, T: ExpressibleByFloatLiteral {

let rows: Int
let columns: Int
var grid: [T]

public init(rows: Int, columns: Int, repeatedValue: T) {
self.rows = rows
self.columns = columns

self.grid = [T](repeating: repeatedValue, count: rows * columns)
}
}

extension Matrix: Sequence {
public func makeIterator() -> AnyIterator<ArraySlice<T>> {
let endIndex = rows * columns
var nextRowStartIndex = 0

return AnyIterator {
if nextRowStartIndex == endIndex {
return nil
}

let currentRowStartIndex = nextRowStartIndex
nextRowStartIndex += self.columns

return self.grid[currentRowStartIndex..<nextRowStartIndex]
}
}
}

This compiles and runs with both Swift 3 and 4.

Collection' requires the types 'MyCollectionClass.Element' and 'Slice MyCollectionClass ' be equivalent

It's a completely useless error message (which I would encourage you to file a bug over) – the problem is twofold:

  • You're confusing the compiler by interchangeably using Int and Index.
  • You're referring to SubSequence without actually having satisfied that associated type.

You can solve both of these by just defining type aliases in order to explicitly satisfy both the Index and SubSequence associated types:

public class MyCollectionClass<MyCollectionElement> {
var _values = [MyCollectionElement]()
}

extension MyCollectionClass: Collection {

public typealias Element = MyCollectionElement
public typealias Index = Int

// as ArraySlice is Array's SubSequence type.
public typealias SubSequence = ArraySlice<MyCollectionElement>

public var startIndex: Index {
return _values.startIndex
}

public var endIndex: Index {
return _values.endIndex
}

public func index(after: Index) -> Index {
return _values.index(after: after)
}

public subscript(position: Index) -> Element {
return _values[position]
}

public subscript(bounds: Range<Index>) -> SubSequence {
return _values[bounds]
}
}

Although note that you don't have to implement the subscript(bounds:) requirement – Collection offers a default implementation for that, which simply returns a Slice<Self>.

Also, if possible, I would rename your (assumed) generic placeholder just to Element, and have the compiler infer that the placeholder satisfies the Element associated type from the subscript declaration:

public class MyCollectionClass<Element> {
var _values = [Element]()
}

extension MyCollectionClass: Collection {

public typealias Index = Int

public var startIndex: Index {
return _values.startIndex
}

public var endIndex: Index {
return _values.endIndex
}

public func index(after: Index) -> Index {
return _values.index(after: after)
}

public subscript(position: Index) -> Element {
return _values[position]
}
}

Why popFirst throws an error, but removeFirst works?

The error is improved in Swift 4.2:

error: ios.playground:4:25: error: '[T]' requires the types '[T]' and 'ArraySlice<T>' be equivalent to use 'popFirst'
return elements.popFirst() // ERROR!
^

You get the error because popFirst is not defined for all Collections. It's only defined if the Collection is its own SubSequence type. Here's the implementation:

extension Collection where SubSequence == Self {
/// Removes and returns the first element of the collection.
///
/// - Returns: The first element of the collection if the collection is
/// not empty; otherwise, `nil`.
///
/// - Complexity: O(1)
@inlinable
public mutating func popFirst() -> Element? {
// TODO: swift-3-indexing-model - review the following
guard !isEmpty else { return nil }
let element = first!
self = self[index(after: startIndex)..<endIndex]
return element
}
}

The extension requires SubSequence == Self. Self (with a capital S) is the type of self (with a lower-case s). It is the type on which you're calling popFirst. In your code, Self is Array<T>, also spelled [T].

The constraint is necessary for this line of popFirst to compile:

self = self[index(after: startIndex)..<endIndex]

^__^ ^_______________________________________^
| |
| This is a SubSequence.
|
This is a Self.

self[index(after: startIndex)..<endIndex] is a SubSequence.

Swift can only assign a SubSequence to Self if it knows that Self == SubSequence.

Array's SubSequence type is ArraySlice. Since ArraySlice is not the same type as Array, this extension doesn't apply to Array.

Swift Error Cannot convert value of type '[String.Element]' (aka 'Array Character ') to expected argument type '[String]'

The problem is that Array(allWords[0]) produces [Character] and not the [String] that you need.

You can call map on a String (which is a collection of Characters and use String.init on each character to convert it to a String). The result of the map will be [String]:

var arrayOfLetters = allWords[0].map(String.init)

Notes:

  1. When I tried this in a Playground, I was getting the mysterious message Fatal error: Only BidirectionalCollections can be advanced by a negative amount. This seems to be a Playground issue, because it works correctly in an app.
  2. Just the word "Leopards" produces 109,536 permutations.

Another Approach

Another approach to the problem is to realize that permute doesn't have to work on [String]. It could use [Character] instead. Also, since you are always starting with a String, why not pass that string to the outer permute and let it create the [Character] for you.

Finally, since it is logical to think that you might just want anagrams of the original word, make minStringLen an optional with a value of nil and just use word.count if the value is not specified.

func permute(word: String, minStringLen: Int? = nil) -> Set<String> {
func permute(fromList: [Character], toList: [Character], minStringLen: Int, set: inout Set<String>) {
if toList.count >= minStringLen {
set.insert(String(toList))
}
if !fromList.isEmpty {
for (index, item) in fromList.enumerated() {
var newFrom = fromList
newFrom.remove(at: index)
permute(fromList: newFrom, toList: toList + [item], minStringLen: minStringLen, set: &set)
}
}
}

var set = Set<String>()
permute(fromList: Array(word), toList:[], minStringLen: minStringLen ?? word.count, set: &set)
return set
}

Examples:

print(permute(word: "foo", minStringLen: 1))
["of", "foo", "f", "fo", "o", "oof", "oo", "ofo"]
print(permute(word: "foo"))
["foo", "oof", "ofo"]

Swift Error: Cannot convert value of type 'ArraySlice' to expected argument type

You need to convert ArraySlice to Array using method Array(Slice<Type>)

if (self.points?.count >= 5) {
let lastFivePoints = Array(self.points![(self.points!.count-5)..<self.points!.count])
let angle = VectorCalculator.angleWithArrayOfPoints(lastFivePoints)
}

How can I perform an Array Slice in Swift?

The problem is that mentions[0...3] returns an ArraySlice<String>, not an Array<String>. Therefore you could first use the Array(_:) initialiser in order to convert the slice into an array:

let first3Elements : [String] // An Array of up to the first 3 elements.
if mentions.count >= 3 {
first3Elements = Array(mentions[0 ..< 3])
} else {
first3Elements = mentions
}

Or if you want to use an ArraySlice (they are useful for intermediate computations, as they present a 'view' onto the original array, but are not designed for long term storage), you could subscript mentions with the full range of indices in your else:

let slice : ArraySlice<String> // An ArraySlice of up to the first 3 elements
if mentions.count >= 3 {
slice = mentions[0 ..< 3]
} else {
slice = mentions[mentions.indices] // in Swift 4: slice = mentions[...]
}

Although the simplest solution by far would be just to use the prefix(_:) method, which will return an ArraySlice of the first n elements, or a slice of the entire array if n exceeds the array count:

let slice = mentions.prefix(3) // ArraySlice of up to the first 3 elements

Referencing instance method 'stringify()' on 'Collection' requires the types 'Int' and 'Stringify' be equivalent

extension Collection where Iterator.Element == Stringify 

has a “same type requirement” and defines an extension for collections whose elements are of the type Stringify. But test is an array of Int, i.e. the elements conform to the Stringify protocol. So what you want is

extension Collection where Iterator.Element : Stringify

or, equivalently,

extension Collection where Element : Stringify

The reason that

/// does work
[6,5,34].stringify()

compiles with your original definition is that the compiler infers the type of the array as [Stringify] from the context.

let test: [Stringify] = [5,6,7]
test.stringify()

would compile as well.


Note that there is no need to cast self in the extension method. You can simplify the implementation to

func stringify() -> [String] {
var strings = [String]()
for element in self {
strings.append(element.stringify())
}
return strings
}

or just

func stringify() -> [String] {
return self.map { $0.stringify() }
}

Swift closure: Cannot convert value of type '(_) - Bool' to expected argument type

Something flakey is happening with Swift's type inference. Give card an explicit type and it will work.

return hand.filter({ (card: Card) -> Bool in return card.type == .Red })

You don't need the return type or the return:

return hand.filter({ (card: Card) in card.type == .Red })

Note: this works also:

return hand.filter({ ($0 as Card).type == .Red })

Fully specifying the .Red enum value resolves the issue as well:

return hand.filter({ $0.type == Card.CardType.Red })

It was mentioned in the comments that if you move the definition of Card into the same file as the filter, that it works. In fact, if you split the definition of the CardType enum out from Card and just move CardType into the file with the filter, it works.

Implement `Array` & `ArraySlice` extension with a protocol instead

In order to call indices.groupSplitIndices() you need the constraint

Indices == CountableRange<Index> on the collection extension,
and that requires Index to be Strideable:

extension RandomAccessCollection where Index: Strideable, Indices == CountableRange<Index> {

typealias EqualTest = (Iterator.Element, Iterator.Element) -> Bool

func groupSplitIndices(withEqualTest equal: EqualTest) -> [Index] {
return indices.groupSplitIndices(withEqualTest: {
equal(self[$0], self[$1])
})
}
}

extension CountableRange {
typealias EqualTest = (Element, Element) -> Bool

func groupSplitIndices(withEqualTest equal: EqualTest) -> [Element] {
// Dummy implementation:
return []
}
}

and this actually compiles with Swift 4 (Xcode 9 beta or Xcode 8.3.3 with the Swift 4 toolchain).

There is one problem though: The Swift 3 compiler in Xcode 8.3.3 crashes when compiling the
above code with the "Debug" configuration. That seems to be a compiler
bug, because it compiles without problem in the "Release" configuration,
and also with Xcode 9 or with Xcode 8.3.2 and the Swift 4 toolchain.


Here is a rough description how I figured out the above solution.
Let's start with your "Attempt 3":

extension RandomAccessCollection where Indices: CountableRange<Int>

// error: type 'Indices' constrained to non-protocol type 'CountableRange<Int>

Indices can not be a subclass of or a type adopting CountableRange<Int>, which means that we need a same-typre requirement:

extension RandomAccessCollection where Indices == CountableRange<Int>

This results in

// error: cannot subscript a value of type 'Self' with an index of type 'Int'

at self[$0] and self[$1]. The subscript method of Collection
takes a Self.Index parameter, so we change it to

extension RandomAccessCollection where Indices == CountableRange<Index>

// error: type 'Self.Index' does not conform to protocol '_Strideable'

So Index must be Strideable:

extension RandomAccessCollection where Index: Strideable, Indices == CountableRange<Index>

and that's it!



Related Topics



Leave a reply



Submit