[Proposal]Allow constraints on associatedtype and shorten type constraints list in function


#1

Hello swift community,

I want to introduce a proposal to allow constraints on associatedtype.
I found a bug report(https://bugs.swift.org/browse/SR-1466) and it's due to
without constraints on associatedtype itself.

This force us always have to write the redundant constraints like
Indices.Iterator.Element
== Index or Indices.SubSequence.Iterator.Element == Index on type
constraints in function:

public extension MutableCollection where Self : RandomAccessCollection,
Indices.Index == Index, Indices.SubSequence : RandomAccessCollection,
Indices.SubSequence.Iterator.Element == Index {

    /// Shuffle `self` in-place.

    mutating func shuffle() {

        for i in self.indices.dropLast() {

            let j = self.indices.suffix(from: i).random()!

            if i != j {

                swap(&self[i], &self[j])

            }

        }

    }

}

Besides this, we also can write some odd definitions but allowed by swift
compiler.

struct MyArray : Collection {

    typealias Indices = CountableRange<Int32>

    var base: [Int]

    var startIndex: Int {

        return base.startIndex

    }

    var endIndex: Int {

        return base.endIndex

    }

    func index(after: Int) -> Int {

        return after + 1

    }

    var indices: CountableRange<Int32> {

        return CountableRange(uncheckedBounds: (lower: Int32(startIndex),
upper: Int32(endIndex)))

    }

    subscript(position: Int) -> Int {

        get {

            return base[position]

        }

        set {

            base[position] = newValue

        }

    }

}

as a reference:
http://stackoverflow.com/questions/37581234/can-an-associated-type-be-restricted-by-protocol-conformance-and-a-where-clause

it's clearly that we need a syntax like this:

public protocol Collection : Indexable, Sequence {

    /// A sequence that represents a contiguous subrange of the collection's

    /// elements.

    ///

    /// This associated type appears as a requirement in the `Sequence`

    /// protocol, but it is restated here with stricter constraints. In a

    /// collection, the subsequence should also conform to `Collection`.

    associatedtype SubSequence : IndexableBase, Sequence where
SubSequence.Iterator.Element == Iterator.Element = Slice<Self>

    /// A type that can represent the indices that are valid for
subscripting the

    /// collection, in ascending order.

    associatedtype Indices : IndexableBase, Sequence where
Indices.Iterator.Element == Index = DefaultIndices<Self>

}

This harmless and brings huge benefits to swift.


(Anders) #2

It is one of the items in the Generics Manifesto, and we had a discussion thread with a proposal on this already, however halted for being an addictive feature. Anyway, aren't discussions on post Swift 3 matters preferred to start on Aug 1?

Hart's proposal
https://github.com/hartbit/swift-evolution/blob/master/proposals/XXXX-powerful-constraints-associated-types.md

[swift-evolution] [Proposal] More Powerful Constraints for Associated Types
https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20160502/016354.html

Regards,
Anders

···

On 29 Jul 2016, at 10:17 AM, Susan Cheng via swift-evolution <swift-evolution@swift.org> wrote:

Hello swift community,

I want to introduce a proposal to allow constraints on associatedtype.
I found a bug report(https://bugs.swift.org/browse/SR-1466) and it's due to without constraints on associatedtype itself.

This force us always have to write the redundant constraints like Indices.Iterator.Element == Index or Indices.SubSequence.Iterator.Element == Index on type constraints in function:

public extension MutableCollection where Self : RandomAccessCollection, Indices.Index == Index, Indices.SubSequence : RandomAccessCollection, Indices.SubSequence.Iterator.Element == Index {
    
    /// Shuffle `self` in-place.
    mutating func shuffle() {
        for i in self.indices.dropLast() {
            let j = self.indices.suffix(from: i).random()!
            if i != j {
                swap(&self[i], &self[j])
            }
        }
    }
}

Besides this, we also can write some odd definitions but allowed by swift compiler.

struct MyArray : Collection {
    
    typealias Indices = CountableRange<Int32>
    
    var base: [Int]
    
    var startIndex: Int {
        return base.startIndex
    }
    var endIndex: Int {
        return base.endIndex
    }

    func index(after: Int) -> Int {
        return after + 1
    }
    
    var indices: CountableRange<Int32> {
        return CountableRange(uncheckedBounds: (lower: Int32(startIndex), upper: Int32(endIndex)))
    }
    
    subscript(position: Int) -> Int {
        get {
            return base[position]
        }
        set {
            base[position] = newValue
        }
    }
}

as a reference: http://stackoverflow.com/questions/37581234/can-an-associated-type-be-restricted-by-protocol-conformance-and-a-where-clause

it's clearly that we need a syntax like this:

public protocol Collection : Indexable, Sequence {
    
    /// A sequence that represents a contiguous subrange of the collection's
    /// elements.
    ///
    /// This associated type appears as a requirement in the `Sequence`
    /// protocol, but it is restated here with stricter constraints. In a
    /// collection, the subsequence should also conform to `Collection`.
    associatedtype SubSequence : IndexableBase, Sequence where SubSequence.Iterator.Element == Iterator.Element = Slice<Self>
    
    /// A type that can represent the indices that are valid for subscripting the
    /// collection, in ascending order.
    associatedtype Indices : IndexableBase, Sequence where Indices.Iterator.Element == Index = DefaultIndices<Self>

}

This harmless and brings huge benefits to swift.
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


#3

Thanks.

I found this proposal in pull requests after the email sent.

Anders Ha <hello@andersio.co> 於 2016年7月29日星期五 寫道:

···

It is one of the items in the Generics Manifesto, and we had a discussion
thread with a proposal on this already, however halted for being an
addictive feature. Anyway, aren't discussions on post Swift 3 matters
preferred to start on Aug 1?

Hart's proposal

https://github.com/hartbit/swift-evolution/blob/master/proposals/XXXX-powerful-constraints-associated-types.md

[swift-evolution] [Proposal] More Powerful Constraints for Associated Types

https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20160502/016354.html

Regards,
Anders

On 29 Jul 2016, at 10:17 AM, Susan Cheng via swift-evolution < > swift-evolution@swift.org > <javascript:_e(%7B%7D,'cvml','swift-evolution@swift.org');>> wrote:

Hello swift community,

I want to introduce a proposal to allow constraints on associatedtype.
I found a bug report(https://bugs.swift.org/browse/SR-1466) and it's due
to without constraints on associatedtype itself.

This force us always have to write the redundant constraints like Indices.Iterator.Element
== Index or Indices.SubSequence.Iterator.Element == Index on type
constraints in function:

public extension MutableCollection where Self : RandomAccessCollection,
Indices.Index == Index, Indices.SubSequence : RandomAccessCollection,
Indices.SubSequence.Iterator.Element == Index {

    /// Shuffle `self` in-place.
    mutating func shuffle() {
        for i in self.indices.dropLast() {
            let j = self.indices.suffix(from: i).random()!
            if i != j {
                swap(&self[i], &self[j])
            }
        }
    }
}

Besides this, we also can write some odd definitions but allowed by swift
compiler.

struct MyArray : Collection {

    typealias Indices = CountableRange<Int32>

    var base: [Int]

    var startIndex: Int {
        return base.startIndex
    }
    var endIndex: Int {
        return base.endIndex
    }

    func index(after: Int) -> Int {
        return after + 1
    }

    var indices: CountableRange<Int32> {
        return CountableRange(uncheckedBounds: (lower: Int32(startIndex),
upper: Int32(endIndex)))
    }

    subscript(position: Int) -> Int {
        get {
            return base[position]
        }
        set {
            base[position] = newValue
        }
    }
}

as a reference:
http://stackoverflow.com/questions/37581234/can-an-associated-type-be-restricted-by-protocol-conformance-and-a-where-clause

it's clearly that we need a syntax like this:

public protocol Collection : Indexable, Sequence {

    /// A sequence that represents a contiguous subrange of the
collection's
    /// elements.
    ///
    /// This associated type appears as a requirement in the `Sequence`
    /// protocol, but it is restated here with stricter constraints. In a
    /// collection, the subsequence should also conform to `Collection`.
    associatedtype SubSequence : IndexableBase, Sequence where
SubSequence.Iterator.Element == Iterator.Element = Slice<Self>

    /// A type that can represent the indices that are valid for
subscripting the
    /// collection, in ascending order.
    associatedtype Indices : IndexableBase, Sequence where
Indices.Iterator.Element == Index = DefaultIndices<Self>

}

This harmless and brings huge benefits to swift.
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
<javascript:_e(%7B%7D,'cvml','swift-evolution@swift.org');>
https://lists.swift.org/mailman/listinfo/swift-evolution