<html><head><meta http-equiv="Content-Type" content="text/html charset=utf-8"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class="">Covariant generic types make for an unsound type system. I believe the reason why Array and Optional are covariant in their generic parameter is that the way their implementation interacts with their internal storage assures that new storage is created if types mismatch: this means that to make covariance work for generic types you have to be extra careful when using references, because it doesn't really make sense from a mathematical standpoint (from my understanding of the matter).<div class=""><br class=""></div><div class="">What could probably be useful in your case is the concept of "generalized existential", which is considered in the generics manifesto ( <a href="https://github.com/apple/swift/blob/master/docs/GenericsManifesto.md#generalized-existentials" class="">https://github.com/apple/swift/blob/master/docs/GenericsManifesto.md#generalized-existentials</a> ) and I believe is something that will eventually be added to Swift in the future because many use cases have come up in the mailing list over time: for example smart KeyPaths were implemented with classes instead of structs and protocols because of the lack of generalized existentials in the language.</div><div class=""><br class=""></div><div class=""><br class=""></div><div class="">Elviro <div class=""><br class=""></div><div class=""><br class=""><div><blockquote type="cite" class=""><div class="">Il giorno 08 ago 2017, alle ore 00:00, Logan Shire via swift-evolution <<a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a>> ha scritto:</div><br class="Apple-interchange-newline"><div class=""><meta http-equiv="Content-Type" content="text/html charset=utf-8" class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class="">One of my longstanding frustrations with generic types and protocols has been how hard it is to work with them when their type is unspecified.<div class="">Often I find myself wishing that I could write a function that takes a generic type or protocol as a parameter, but doesn’t care what its generic type is.</div><div class=""><br class=""></div><div class="">For example, if I have a type:</div><div class=""><br class=""></div><div class=""><div class="" style="margin: 0px; line-height: normal; font-family: Menlo; color: rgb(255, 255, 255); background-color: rgb(40, 43, 53);"><span class="" style="color: rgb(194, 52, 155);">struct</span> Foo<T> {</div><div class="" style="margin: 0px; line-height: normal; font-family: Menlo; color: rgb(255, 255, 255); background-color: rgb(40, 43, 53);"> <span class="" style="color: rgb(194, 52, 155);">let</span> name: <span class="" style="color: rgb(0, 175, 202);">String</span></div><div class="" style="margin: 0px; line-height: normal; font-family: Menlo; color: rgb(255, 255, 255); background-color: rgb(40, 43, 53);"> <span class="" style="color: rgb(194, 52, 155);">let</span> value: <span class="" style="color: rgb(147, 201, 106);">T</span></div><div class="" style="margin: 0px; line-height: normal; font-family: Menlo; color: rgb(255, 255, 255); background-color: rgb(40, 43, 53);">}</div></div><div class=""><br class=""></div><div class="">or:</div><div class=""><br class=""></div><div class=""><div class="" style="margin: 0px; line-height: normal; font-family: Menlo; color: rgb(255, 255, 255); background-color: rgb(40, 43, 53);"><span class="" style="color: rgb(194, 52, 155);">protocol</span> Foo {</div><div class="" style="margin: 0px; line-height: normal; font-family: Menlo; color: rgb(255, 255, 255); background-color: rgb(40, 43, 53);"> <span style="color: rgb(194, 52, 155);" class="">associatedtype </span><span style="color: rgb(147, 201, 106);" class="">T</span></div><div class="" style="margin: 0px; line-height: normal; font-family: Menlo; color: rgb(255, 255, 255); background-color: rgb(40, 43, 53);"> <span class="" style="color: rgb(194, 52, 155);">var</span> name: <span class="" style="color: rgb(0, 175, 202);">String </span>{ <span style="color: rgb(194, 52, 155);" class="">get </span>}</div><div class="" style="margin: 0px; line-height: normal; font-family: Menlo; color: rgb(255, 255, 255); background-color: rgb(40, 43, 53);"> <span class="" style="color: rgb(194, 52, 155);">var</span> value: <span class="" style="color: rgb(147, 201, 106);">T </span>{ <span style="color: rgb(194, 52, 155);" class="">get </span>}</div><div class="" style="margin: 0px; line-height: normal; font-family: Menlo; color: rgb(255, 255, 255); background-color: rgb(40, 43, 53);">}</div></div><div class=""><br class=""></div><div class="">And I want to write a function that only cares about Foo.name, I’d like to be able to:</div><div class=""><br class=""></div><div class=""><div class="" style="margin: 0px; line-height: normal; font-family: Menlo; color: rgb(255, 255, 255); background-color: rgb(40, 43, 53);"><span class="" style="color: rgb(194, 52, 155);">func</span> sayHi(to foo: <span class="" style="text-decoration: underline; color: rgb(0, 175, 202);">F</span><span class="" style="color: rgb(0, 175, 202);">oo</span>) {</div><div class="" style="margin: 0px; line-height: normal; font-family: Menlo; color: rgb(255, 255, 255); background-color: rgb(40, 43, 53);"> <span class="" style="color: rgb(0, 175, 202);">print</span>(<span class="" style="color: rgb(228, 67, 71);">"hi </span>\<span class="" style="color: rgb(228, 67, 71);">(</span>foo.name<span class="" style="color: rgb(228, 67, 71);">)"</span>)</div><div class="" style="margin: 0px; line-height: normal; font-family: Menlo; color: rgb(255, 255, 255); background-color: rgb(40, 43, 53);">}</div></div><div class=""><br class=""></div><div class="">But instead I get the error, “Reference to generic type Foo requires arguments in <…>”</div><div class=""><br class=""></div><div class="">Also, when you want to have a polymorphic array of generic types, you can’t:</div><div class=""><br class=""></div><div class=""><div class="" style="margin: 0px; line-height: normal; font-family: Menlo; color: rgb(255, 255, 255); background-color: rgb(40, 43, 53);"><span class="" style="color: rgb(194, 52, 155);">let</span> foos: [Foo] = [<span class="" style="color: rgb(147, 201, 106);">Foo</span>(name: <span class="" style="color: rgb(228, 67, 71);">"Int"</span>, value: <span class="" style="color: rgb(139, 132, 207);">2</span>), <span class="" style="color: rgb(147, 201, 106);">Foo</span>(name: <span class="" style="color: rgb(228, 67, 71);">"Double"</span>, value: <span class="" style="color: rgb(139, 132, 207);">2.0</span>)]</div></div><div class=""><br class=""></div><div class="">And if you remove the explicit type coercion, you just get [Any]</div><div class=""><br class=""></div><div class=""><span class="" style="font-family: Menlo; background-color: rgb(40, 43, 53); color: rgb(194, 52, 155);">let</span><span class="" style="color: rgb(255, 255, 255); font-family: Menlo; background-color: rgb(40, 43, 53);"> foos = [</span><span class="" style="font-family: Menlo; background-color: rgb(40, 43, 53); color: rgb(147, 201, 106);">Foo</span><span class="" style="color: rgb(255, 255, 255); font-family: Menlo; background-color: rgb(40, 43, 53);">(name: </span><span class="" style="font-family: Menlo; background-color: rgb(40, 43, 53); color: rgb(228, 67, 71);">"Int"</span><span class="" style="color: rgb(255, 255, 255); font-family: Menlo; background-color: rgb(40, 43, 53);">, value: </span><span class="" style="font-family: Menlo; background-color: rgb(40, 43, 53); color: rgb(139, 132, 207);">2</span><span class="" style="color: rgb(255, 255, 255); font-family: Menlo; background-color: rgb(40, 43, 53);">), </span><span class="" style="font-family: Menlo; background-color: rgb(40, 43, 53); color: rgb(147, 201, 106);">Foo</span><span class="" style="color: rgb(255, 255, 255); font-family: Menlo; background-color: rgb(40, 43, 53);">(name: </span><span class="" style="font-family: Menlo; background-color: rgb(40, 43, 53); color: rgb(228, 67, 71);">"Double"</span><span class="" style="color: rgb(255, 255, 255); font-family: Menlo; background-color: rgb(40, 43, 53);">, value: </span><span class="" style="font-family: Menlo; background-color: rgb(40, 43, 53); color: rgb(139, 132, 207);">2.0</span><span class="" style="color: rgb(255, 255, 255); font-family: Menlo; background-color: rgb(40, 43, 53);">)]</span></div><div class=""><br class=""></div><div class="">I wish that could be inferred to be [Foo]. I’d like to propose being able to use the non-generic interface of a type normally. </div><div class="">I.e. if you have a type Foo<T>, it is implicitly of type Foo as well. The type Foo could be used like any other type.</div><div class="">It could be a parameter in a function, a variable, or even the generic type of another type (like a Dictionary<String, Foo>)</div><div class=""><br class=""></div><div class="">The only restriction is that if you want to call or access, directly or indirectly, a function or member that requires the generic type,</div><div class="">the generic type would have to be known at that point.</div><div class=""><br class=""></div><div class="">Foo<T> should be able to be implicitly casted to Foo wherever you want, and Foo could be cast to Foo<T> conditionally.</div><div class="">Initializers would still obviously have to know the generic type, but given the above example, you should be able to:</div><div class=""><br class=""></div><div class=""><div class="" style="margin: 0px; line-height: normal; font-family: Menlo; color: rgb(255, 255, 255); background-color: rgb(40, 43, 53);"><span class="" style="color: rgb(194, 52, 155);">let</span> names = <span class="" style="color: rgb(147, 201, 106);">foos</span>.<span class="" style="color: rgb(0, 175, 202);">map</span> { $0.<span class="" style="color: rgb(147, 201, 106);">name</span> }</div></div><div class=""><br class=""></div><div class="">However, you could not do the following:</div><div class=""><br class=""></div><div class=""><div style="margin: 0px; line-height: normal; font-family: Menlo; color: rgb(255, 255, 255); background-color: rgb(40, 43, 53);" class=""><span style="color: #c2349b" class="">let</span> foos = [<span style="color: #93c96a" class="">Foo</span>]()</div></div><div class=""><br class=""></div><div class="">Because the initializer would need to know the generic type in order to allocate the memory.</div><div class=""><br class=""></div><div class="">Let me know what you think!</div><div class=""><br class=""></div><div class="">—</div><div class=""><br class=""></div><div class="">Logan Shire</div><div class="">iOS @ Lyft</div><div class=""><br class=""></div></div>_______________________________________________<br class="">swift-evolution mailing list<br class=""><a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a><br class="">https://lists.swift.org/mailman/listinfo/swift-evolution<br class=""></div></blockquote></div><br class=""></div></div></body></html>