Dictionary of protocol conforming values is ambiguous?

162 views Asked by At

I'm trying create a "conversion" Protocol, to which a Dictionary can conform to if its values implement said protocol.

import Foundation

protocol Fooable {
    var foo:String { get }
}

extension Double:Fooable {
    var foo:String { get { return "number" } }
}

extension Int:Fooable {
    var foo:String { get { return "count" } }
}

extension String:Fooable {
    var foo:String { get { return "name" } }
}

extension Dictionary:Fooable where Key == String, Value:Fooable {
    var foo:String {
        get {
            var result = "["
            self.keys.sorted().forEach { key in
                result += key
                result += ": "
                result += self[key]!.foo
            }
            result += "]"
            return result
        }
    }
}

["a": 6.28, "b": 42, "c": "boo"].foo

The problem is that the last line is deemed ambiguous:

error: type of expression is ambiguous without more context
["a": 6.28, "b": 42, "c": "boo"].foo
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~

Is what I'm trying to do even doable? What do I have to change or add to make it work?

UPDATE

Type Erasure seems to be one "solution". So basically, I would need to make something like:

struct AnyFoo<Fooable> { }

At this point, I can now wrap/erase everything in my dictionary literal:

["a": AnyFoo(6.28), "b": AnyFoo(42), "c": AnyFoo("boo")].foo

along with refining the extension of Dictionary to be for Dictionary's where Value is AnyFoo. Is this really any better than just constricting the Dictionary's extension to cases where Value is String instead and just doing:

["a": 6.28.foo, "b": 42.foo, "c": "boo".foo].foo

For a simple "convert" case, I'm not sure what I would gain from using TypeErasure to defer the conversion through a wrapper, vs just converting before dictionary creation. Less actual typing (as in character input) to do the latter. So I haven't really gained any thing.

Unless I'm missing something, for my case, I'll probably just go with downcasts (e.g. as? Fooable) for container elements, and do something like log errors or something.

0

There are 0 answers