{"id":2876,"date":"2014-07-26T14:08:17","date_gmt":"2014-07-26T17:08:17","guid":{"rendered":"http:\/\/brockerhoff.net\/blog\/?p=2876"},"modified":"2014-08-06T20:37:05","modified_gmt":"2014-08-06T23:37:05","slug":"swift-learning-about-type-constraints","status":"publish","type":"post","link":"https:\/\/brockerhoff.net\/blog\/2014\/07\/26\/swift-learning-about-type-constraints\/","title":{"rendered":"Swift: learning about type constraints"},"content":{"rendered":"<p>My first reading of the Swift books and of the generated Swift library header (remember, you can see the header by command-double-clicking on any Swift type) left me quite confused about the proper way to write generics and extensions to generics.<\/p>\n<p>As usual, I favor learning-by-doing for such things <em>[skydiving joke omitted]<\/em> \u2014 I paged through a book on \u201cType Theory\u201d to no avail \u2014 so, in a recent update to my <a href=\"https:\/\/github.com\/rbrockerhoff\/SwiftChecker\" target=\"_blank\">SwiftChecker app<\/a> I tried to include a useful extension.<\/p>\n<p>Here is a (slightly edited) part of it:<\/p>\n<pre><code>public extension Dictionary {\r\n\t\/**\tMerges a sequence of values into a Dictionary by specifying\r\n\t\ta filter function. The filter function can return nil to filter\r\n\t\tout that item from the input Sequence, or return a (key,value)\r\n\t\ttuple to insert or change an item. In that case, value can be\r\n\t\tnil to remove the item for that key. *\/\r\n\tmutating func merge &lt;T, S: SequenceType where S.Generator.Element == T&gt;\r\n\t\t(seq: S, filter: (T) -&gt; (Key, Value?)?) {\r\n\t\tvar gen = seq.generate()\r\n\t\twhile let t: T = gen.next() {\r\n\t\t\tif let (key: Key, value: Value?) = filter(t) {\r\n\t\t\t\tself[key] = value\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\t\/\/ end of Dictionary extension<\/code><\/pre>\n<p>To explain this, first recall that types can include <code>typealias<\/code> declarations within their definitions; this is much used for generic types, but can also be used everywhere. Here&#8217;s the declaration for <code>Sequence<\/code> from the library header:<\/p>\n<pre><code>protocol SequenceType : _Sequence_Type {\r\n    typealias Generator : GeneratorType\r\n    func generate() -&gt; Generator\r\n}\r\n<\/code><\/pre>\n<p>and of the <code>GeneratorType<\/code> protocol it uses:<\/p>\n<pre><code>protocol GeneratorType {\r\n    typealias Element\r\n    mutating func next() -&gt; Element?\r\n}\r\n<\/code><\/pre>\n<p>Going backwards: the <code>GeneratorType<\/code> protocol defines an associated type with the <code>typealias<\/code> declaration, in this case, <code>Element<\/code>. This is a placeholder type that will become an actual type when the protocol is adopted. These associated types form a hierarchy, so that you can refer to <code>GeneratorType.Element<\/code> and, further up, to <code>Sequence.Generator.Element<\/code>, and so forth.<\/p>\n<p>Now look again at the <code>merge<\/code> method I define in my extension to <code>Dictionary<\/code>:<\/p>\n<pre><code>\tmutating func merge &lt;T, S: SequenceType where S.Generator.Element == T&gt;\r\n\t\t(seq: S, filter: (T) -&gt; (Key, Value?)?) { \/\/ ... etc.\r\n<\/code><\/pre>\n<p>Inside the &lt;&gt; after the method name are the type constraints. When I call <code>merge<\/code> on a <code>Dictionary<\/code>, this means that:<\/p>\n<ul>\n<li><code>T<\/code> is a placeholder type (with no constraints) used for the rest of the definition<\/li>\n<li><code>S<\/code> is another placeholder that is constrained to conform to the <code>SequenceType<\/code> protocol, and further (by using the <code>where<\/code> clause)<\/li>\n<li>the <code>generate()<\/code> function for <code>S<\/code> must return a <code>Generator<\/code> whose <code>Element<\/code> is equal to <code>T<\/code>, and also<\/li>\n<li><code>T<\/code> is inferred from the argument type of the function\/closure passed as the last argument to <code>merge<\/code>, and finally<\/li>\n<li>this function\/closure must return an <code>Optional<\/code> tuple of type <code>(Key, Value?)<\/code>.<\/li>\n<\/ul>\n<p>But what is this <code>(Key, Value?)<\/code> type, then? Recall that we&#8217;re extending <code>Dictionary<\/code>, so that type&#8217;s associated type hierarchy is also available; checking the declaration in the library header, we see:<\/p>\n<pre><code>struct Dictionary&lt;Key : Hashable, Value&gt; : CollectionType, DictionaryLiteralConvertible {\r\n    typealias Element = (Key, Value)\r\n    typealias Index = DictionaryIndex&lt;Key, Value&gt;\r\n    ... etc.\r\n<\/code><\/pre>\n<p>so our type constraint will match <code>Key<\/code>\u00a0and <code>Value<\/code>\u00a0to those pertaining to the particular <code>Dictionary<\/code> that <code>merge<\/code> is being called on! To be more clear, we could even write <code>(Dictionary.Key, Dictionary.Value?)<\/code> in our definition.<\/p>\n<p>Let&#8217;s look at a specific example of that. Notice that, where in the type constraints we refer to the placeholder type names (on the left of\u00a0the\u00a0<code>typealias<\/code>\u00a0declarations), we refer to specific types wherever one is defined.<\/p>\n<pre><code>let strs = [ \"10\", \"11\", \"12\", \"xyz\" ]\t\/\/ this is an Array  and therefore\r\n\t\t\t\t\t\/\/ its Generator.Element is String\r\nlet dict = [ 0:\"0\" ]\t\/\/ this is a Dictionary &lt;Int, String&gt; and therefore\r\n\t\t\t\/\/ its Key is Int and Value is String\r\ndict.merge (strs) { (s) in\t\/\/ s is inferred to be strs's Generator.Element,\r\n\t\t\t\t\/\/ that is, a String\r\n\tlet v = s.toInt()\t\/\/ v is an Optional , will be nil for \"xyz\"\r\n\treturn v ? (v!, s) : nil\t\/\/ returns a valid tuple or nil\r\n}\r\n\/\/ dict will now contain [ 0:\"0\", 10:\"10\", 11:\"11\", 12:\"12\" ]\r\n<\/code><\/pre>\n<p>You can verify that everything matches our type constraints either directly or by type inference. If you change anything that doesn&#8217;t fit \u2014 say, by declaring <code>s<\/code> as anything but <code>String<\/code> inside the closure, or changing the type it returns \u2014 you&#8217;ll see a syntax error. (Assuming, of course, that no other extension has matching constraints.)<\/p>\n<p>That said, currently (Xcode 6.0b5) the library header still has some bugs. Specifically, many type constraints either have too many prefixes removed, or show the wrong hierarchy, so you&#8217;ll see things like <code>&lt;S : Sequence where T == T&gt;<\/code> which won&#8217;t compile if you copy &amp; paste it. No doubt this will be fixed soon.<\/p>\n<p><strong>Update:<\/strong> oops. Fixed the <code>return<\/code>, above.<\/p>\n<p><strong>Update#2:<\/strong>\u00a0updated for Xcode 6.0b5 \u2014 many of those typenames either lost or gained a <code>Type<\/code>\u00a0suffix.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>My first reading of the Swift books and of the generated Swift library header (remember, you can see the header by command-double-clicking on any Swift type) left me quite confused about the proper way to write generics and extensions to generics. As usual, I favor learning-by-doing for such things [skydiving joke omitted] \u2014 I paged [&hellip;]<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"jetpack_post_was_ever_published":false,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[3,4,19],"tags":[47],"class_list":["post-2876","post","type-post","status-publish","format-standard","hentry","category-apple","category-dev","category-software","tag-swift"],"featured_image_src":null,"author_info":{"display_name":"Rainer Brockerhoff","author_link":"https:\/\/brockerhoff.net\/blog\/author\/rbrockerhoff\/"},"jetpack_featured_media_url":"","jetpack_shortlink":"https:\/\/wp.me\/p1q3Zc-Ko","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/brockerhoff.net\/blog\/wp-json\/wp\/v2\/posts\/2876","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/brockerhoff.net\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/brockerhoff.net\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/brockerhoff.net\/blog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/brockerhoff.net\/blog\/wp-json\/wp\/v2\/comments?post=2876"}],"version-history":[{"count":0,"href":"https:\/\/brockerhoff.net\/blog\/wp-json\/wp\/v2\/posts\/2876\/revisions"}],"wp:attachment":[{"href":"https:\/\/brockerhoff.net\/blog\/wp-json\/wp\/v2\/media?parent=2876"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/brockerhoff.net\/blog\/wp-json\/wp\/v2\/categories?post=2876"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/brockerhoff.net\/blog\/wp-json\/wp\/v2\/tags?post=2876"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}