[swift-evolution] [Idea] Generic associated types

Karl Wagner razielim at gmail.com
Sun Mar 12 15:23:30 CDT 2017


> On 12 Mar 2017, at 14:32, Matthew Johnson <matthew at anandabits.com> wrote:
> 
> This is a really important feature IMO, but as others have pointed out it basically amounts to higher-kinded types.  I would love to be wrong about this but I am reasonably sure this is out of scope for Swift 4 (otherwise I would be working on a proposal already).
> 
> Sent from my iPad
> 

I’m not an expert on this stuff, but are they still higher-kinded types if we don’t express a relationship between Self and the associated type? I don’t think it’s quite the same conceptual leap as HKT.

Consider that every associated type must be backed by a typealias (explicit or inferred) in the conforming type. We can already have generic typealiases. This would be a more targeted thing which required those associatedtype-implementing-typealiases to contain generic parameters. It would also extend the constraints from SE-0142 to allow constraints to refer to those parameters and bind them to other associated types.

The workaround is basically to erase and dynamic-cast your way out:

      //NOTE: dynamic type of ScanPromise.Result *must* be same as closure result. No static enforcement though :(

extension Scanner where ScanPromise.Result == Any? {
    func scan<T>(from f: Offset, until u: (Offset, Item) -> T?) -> T? {
        return withoutActuallyEscaping(u) { _u -> T? in
          return promiseScan(from: f, until: _u).await() as? T // downcast from Any? to T?
        }
    }
}

class MyPromise<R>: Promise {
    typealias Result = R?
    let offset: Offset
    let block: (Offset, Item) -> R?
}

class MyScanner: Scanner {
    typealias ScanPromise = MyPromise<Any> // want this to be “typealias ScanPromise<X> = MyPromise<X>"

    func promiseScan<T>(from: Offset, until: @escaping (Offset, Item) -> T?) -> ScanPromise {
        return MyPromise(offset: from, block: until) // upcast from T? to Any?
    }
}

- Karl

> On Mar 11, 2017, at 11:49 PM, Karl Wagner via swift-evolution <swift-evolution at swift.org <mailto:swift-evolution at swift.org>> wrote:
> 
>> I have a model like this:
>> 
>> protocol Promise {
>>     associatedtype Result
>> }
>> 
>> protocol Scanner {
>>     associatedtype ScanPromise: Promise
>> 
>>     func promiseScan<T>(from: Offset, until: (Offset, Item) -> T?) -> ScanPromise // where Result == T?
>> }
>> 
>> The thing that I’m trying to express is: whichever type implements the associated type ‘ScanPromise’ must be generic, and that parameter must be its result (i.e. something it got as a result of calling the “until” closure).
>> 
>> Even with SE-0142, this kind of constraint would not be possible. What I would like to write is something like this:
>> 
>> protocol Promise {
>>     associatedtype Result
>> }
>> 
>> protocol Scanner {
>>     associatedtype ScanPromise<T>: Promise // now generic. [SE-0142]: where Result == T
>> 
>>     func promiseScan<T>(from: Offset, until: (Offset, Item) -> T?) -> ScanPromise<T>
>> }
>> 
>> Thoughts?
>> 
>> - Karl
>> _______________________________________________
>> swift-evolution mailing list
>> swift-evolution at swift.org <mailto:swift-evolution at swift.org>
>> https://lists.swift.org/mailman/listinfo/swift-evolution <https://lists.swift.org/mailman/listinfo/swift-evolution>

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20170312/6ed11f6b/attachment.html>


More information about the swift-evolution mailing list