Search code examples
swiftcollectionsprotocols

Conditionally conform Set to ExpressibleByDictionaryLiteral protocol


protocol Weighted: Hashable {
    associatedtype D: Hashable
    associatedtype W: Hashable
    var destination: D { get }
    var weight: W { get }
    init(destination: D, weight: W)
}   

Approach 1
// Edited ------------
@Dávid Pásztor has answered this part of the question, so I deleted it, to make room for more interesting second part.
// ----------------------

Approach 2

extension ExpressibleByDictionaryLiteral where Self: Collection, Element: Weighted {
    init(dictionaryLiteral elements: (Element.D, Element.W)...) {
        Self.init(elements.map(Element.init))
    }
}

This code compiles. But the next line doesn't:

extension Set: ExpressibleByDictionaryLiteral where Element: Weighted {}

Type 'Set' does not conform to protocol 'ExpressibleByDictionaryLiteral'

I don't understand why it doesn't conform to the protocol. Seems like it should conform at this stage.

Bonus question

extension ExpressibleByDictionaryLiteral where Self: Collection, Element: Weighted {

How to make it extends not for all Collections, but only for Sets?


Solution

  • You simply need to make the Weighted protocol public as well as marking the init public.

    public protocol Weighted: Hashable {
        associatedtype D: Hashable
        associatedtype W: Hashable
        var destination: D { get }
        var weight: W { get }
        init(destination: D, weight: W)
    }
    
    extension Set: ExpressibleByDictionaryLiteral where Element: Weighted {
        public init(dictionaryLiteral elements: (Element.D, Element.W)...) {
            self.init(elements.map(Element.init))
        }
    }