I think this is essential for creating good, general-purpose abstractions with 
Swift.

For example, currently I have a protocol which models a CRUD database. There is 
some ORM behaviour which translates the DB information in to model objects, but 
of course, each database might have different requirements. Currently ORMs use 
class hierarchies to give you that behaviour - e.g. CoreData has 
NSManagedObject, Realm has its own “Object” class, etc. This requires that I 
write separate protocols for each base-type, like this:

protocol RealmObjectStore {
    func create<S>(_ objects: S) where S: Sequence, S.Element: RealmSwift.Object
    func read<T>(_ command: FetchCommand<T>) -> [T] where T: RealmSwift.Object
    // …etc
}

Ideally, my my protocol would look something like this:

protocol ObjectStore {
    associatedtype Storable // might be a concrete type; might be a protocol.

    func create<S>(_ objects: S) where S: Sequence, S.Element: Self.Storable
    func read<T>(_ command: FetchCommand<T>) -> [T] where T: Self.Storable
    // …etc
}

That would allow me to abstract over CoreData and Realm using a single 
protocol, as far as they are both able to act like CRUD databases:

class CoreDataStore: ObjectStore {
    typealias Storable = NSManagedObject
   // …etc
}

class RealmDataStore: ObjectStore {
    typealias Storable = RealmObject
   // …etc
}

Okay, so technically I could do that today by requiring that Storable is a 
subclass of NSObject. But doing this would also us to move beyond class 
hierarchies - what does an ObjectStore really need to store and retrieve its 
data? Well, that depends on the store. Maybe some will require all of the 
dynamism and reflection of Objective-C, and so will continue to require 
subclassing, but maybe for some it will be enough to have Codable conformance 
and a primary key. You could satisfy that with a value-type:

protocol ValueDBStorable: Codable {
    var primaryKey: KeyPath<Self, String> { get }
}

class ValueDBStore: ObjectStore {
    typealias Storable = ValueDBStorable
    // …etc
} 

So I think it’s a very powerful feature and would love to use it. However, I do 
think it would underscore the need for nested protocols.

- Karl


> On 25. Nov 2017, at 00:03, Matthew Johnson via swift-evolution 
> <swift-evolution@swift.org> wrote:
> 
> One of the most frequent frustrations I encounter when writing generic code 
> in Swift is the requirement that supertype constraints be concrete.  When I 
> mentioned this on Twitter 
> (https://twitter.com/anandabits/status/929958479598534656 
> <https://twitter.com/anandabits/status/929958479598534656>) Doug Gregor 
> mentioned that this feature is smaller and mostly straightforward to design 
> and implement (https://twitter.com/dgregor79/status/929975472779288576 
> <https://twitter.com/dgregor79/status/929975472779288576>).
> 
> I currently have a PR open to add the high-level description of this feature 
> found below to the generics manifesto 
> (https://github.com/apple/swift/pull/13012 
> <https://github.com/apple/swift/pull/13012>):
> 
> Currently, supertype constraints may only be specified using a concrete class 
> or protocol type.  This prevents us from abstracting over the supertype.
> 
> ```swift
> protocol P {
>   associatedtype Base
>   associatedtype Derived: Base
> }
> ```
> 
> In the above example `Base` may be any type.  `Derived` may be the same as 
> `Base` or may be _any_ subtype of `Base`.  All subtype relationships 
> supported by Swift should be supported in this context including, but not 
> limited to, classes and subclasses, existentials and conforming concrete 
> types or refining existentials, `T?` and  `T`, `((Base) -> Void)` and 
> `((Derived) -> Void)`, etc.
> 
> Generalized supertype constraints would be accepted in all syntactic 
> locations where generic constraints are accepted.
> 
> I would like to see generalized supertype constraints make it into Swift 5 if 
> possible.  I am not an implementer so I will not be able to bring a proposal 
> forward alone but am interested in collaborating with anyone interested in 
> working on implementation.
> 
> I am also interested in hearing general feedback on this feature from the 
> community at large.  Have you also found this limitation frustrating?  In 
> what contexts?  Does anyone have reservations about introducing this 
> capability?  If so, what are they?
> 
> Matthew
> 
> _______________________________________________
> swift-evolution mailing list
> swift-evolution@swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution


_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

Reply via email to