<div dir="ltr">I've managed to implement this already in the language with a few ugly corners due to the lack of generic protocols.<div><br></div><div>I created a protocol based on Box (<a href="https://github.com/robrix/Box/">https://github.com/robrix/Box/</a>) which works really well. I have extended this to handle certain special protocols like Equatable so you can do SpecialType == SpecialType, and even literalConversion.</div><div><br></div><div>There is however a lot of boilerplate:</div><div><br></div><div>- You have to declare all of your Convertible protocols for converting from one type to another</div><div>- You have to define an empty init so the protocol extensions have something to chain to.</div><div>- You need to write the value property with type.</div><div><br></div><div>Due to the lack of protocol generics, you also need to have a protocol for every type you wish to box which sets the associated type. Of course I could have done this with classes but I wanted to keep this as a value type :).</div><div><br></div><div>With member-wise initializations and generic protocols this could be achievable just by adding a Box protocol to the standard library.</div><div><br></div><div>Here is my implementation of Box as a protocol:</div><div><br></div><div>
<p class=""><b><span class="">protocol</span><span class=""> Box: </span><span class="">CustomStringConvertible</span><span class="">, </span><span class="">CustomDebugStringConvertible</span><span class=""> {</span></b></p>
<p class=""><span class=""><b> </b></span></p>
<p class=""><b><span class=""> </span><span class="">typealias</span><span class=""> FloatLiteralType = Double</span></b></p>
<p class=""><b><span class=""> </span><span class="">typealias</span><span class=""> IntegerLiteralType = Int</span></b></p>
<p class=""><b><span class=""> </span><span class="">typealias</span><span class=""> BoxType = Any</span></b></p>
<p class=""><span class=""><b> </b></span></p>
<p class=""><b><span class=""> </span><span class="">var</span><span class=""> value: </span><span class="">BoxType</span><span class=""> { </span><span class="">get</span><span class=""> </span><span class="">set</span><span class=""> }</span></b></p>
<p class=""><span class=""><b> </b></span></p>
<p class=""><b><span class=""> </span><span class="">init</span><span class="">()</span></b></p>
<p class=""><b><span class=""> </span><span class="">init</span><span class="">(</span><span class="">_</span><span class=""> value: </span><span class="">BoxType</span><span class="">)</span></b></p>
<p class=""><span class=""><b>}</b></span></p>
<p class=""><b><span class=""></span><br></b></p>
<p class=""><b><span class="">extension</span><span class=""> </span><span class="">Box</span><span class=""> </span><span class="">where</span><span class=""> BoxType: CustomStringConvertible {</span></b></p>
<p class=""><span class=""><b> </b></span></p>
<p class=""><b><span class=""> </span><span class="">var</span><span class=""> description: </span><span class="">String</span><span class=""> {</span></b></p>
<p class=""><b><span class=""> </span><span class="">return</span><span class=""> </span><span class="">self</span><span class="">.</span><span class="">value</span><span class="">.</span><span class="">description</span></b></p>
<p class=""><span class=""><b> }</b></span></p>
<p class=""><span class=""><b> </b></span></p>
<p class=""><b><span class=""> </span><span class="">var</span><span class=""> debugDescription: </span><span class="">String</span><span class=""> {</span></b></p>
<p class=""><b><span class=""> </span><span class="">return</span><span class=""> </span><span class="">"</span><span class="">\</span><span class="">(</span><span class="">self</span><span class="">.</span><span class="">value</span><span class="">.</span><span class="">description</span><span class="">)</span><span class="">㎭</span><span class="">"</span></b></p>
<p class=""><span class=""><b> }</b></span></p>
<p class=""><span class=""><b>}</b></span></p>
<p class=""><b><span class=""></span><br></b></p>
<p class=""><span class=""><b>//MARK: FloatingPointBox</b></span></p>
<p class=""><b><span class=""></span><br></b></p>
<p class=""><b><span class="">protocol</span><span class=""> FloatingPointBox: </span><span class="">Box</span><span class="">, </span><span class="">FloatLiteralConvertible</span><span class="">, </span><span class="">IntegerLiteralConvertible</span><span class=""> {</span></b></p>
<p class=""><span class=""><b> </b></span></p>
<p class=""><b><span class=""> </span><span class="">typealias</span><span class=""> BoxType = Double</span></b></p>
<p class=""><b><span class=""> </span><span class="">typealias</span><span class=""> FloatLiteralConvertible = Double</span></b></p>
<p class=""><b><span class=""> </span><span class="">typealias</span><span class=""> IntegerLiteralConvertible = Int</span></b></p>
<p class=""><span class=""><b>}</b></span></p>
<p class=""><b><span class=""></span><br></b></p>
<p class=""><b><span class="">extension</span><span class=""> </span><span class="">Box</span><span class=""> </span><span class="">where</span><span class=""> </span><span class="">Self</span><span class="">.BoxType == Double {</span></b></p>
<p class=""><span class=""><b> </b></span></p>
<p class=""><b><span class=""> </span><span class="">init</span><span class="">(</span><span class="">_</span><span class=""> value: </span><span class="">Double</span><span class="">) {</span></b></p>
<p class=""><span class=""><b> </b></span></p>
<p class=""><b><span class=""> </span><span class="">self</span><span class="">.</span><span class="">init</span><span class="">()</span></b></p>
<p class=""><b><span class=""> </span><span class="">self</span><span class="">.</span><span class="">value</span><span class=""> = value</span></b></p>
<p class=""><span class=""><b> }</b></span></p>
<p class=""><span class=""><b> </b></span></p>
<p class=""><b><span class=""> </span><span class="">init</span><span class="">(</span><span class="">_</span><span class=""> value: </span><span class="">Int</span><span class="">) {</span></b></p>
<p class=""><span class=""><b> </b></span></p>
<p class=""><b><span class=""> </span><span class="">self</span><span class="">.</span><span class="">init</span><span class="">()</span></b></p>
<p class=""><b><span class=""> </span><span class="">self</span><span class="">.</span><span class="">value</span><span class=""> = </span><span class="">Double</span><span class="">(value)</span></b></p>
<p class=""><span class=""><b> }</b></span></p>
<p class=""><span class=""><b>}</b></span></p>
<p class=""><b><span class=""></span><br></b></p>
<p class=""><b><span class="">extension</span><span class=""> </span><span class="">FloatLiteralType</span><span class=""> {</span></b></p>
<p class=""><span class=""><b> </b></span></p>
<p class=""><b><span class=""> </span><span class="">init</span><span class=""><T: </span><span class="">Box</span><span class=""> </span><span class="">where</span><span class=""> </span><span class="">T</span><span class="">.</span><span class="">BoxType</span><span class=""> == </span><span class="">Double</span><span class=""> >(</span><span class="">_</span><span class=""> box: </span><span class="">T</span><span class="">) {</span></b></p>
<p class=""><b><span class=""> </span><span class="">self</span><span class="">.</span><span class="">init</span><span class="">(box.</span><span class="">value</span><span class="">)</span></b></p>
<p class=""><span class=""><b> }</b></span></p>
<p class=""><span class=""><b> </b></span></p>
<p class=""><b><span class=""> </span><span class="">init</span><span class=""><T: </span><span class="">Box</span><span class=""> </span><span class="">where</span><span class=""> </span><span class="">T</span><span class="">.</span><span class="">BoxType</span><span class=""> == </span><span class="">Int</span><span class=""> >(</span><span class="">_</span><span class=""> box: </span><span class="">T</span><span class="">) {</span></b></p>
<p class=""><b><span class=""> </span><span class="">self</span><span class="">.</span><span class="">init</span><span class="">(box.</span><span class="">value</span><span class="">)</span></b></p>
<p class=""><span class=""><b> }</b></span></p>
<p class=""><span class=""><b>}</b></span></p>
<p class=""><b><span class=""></span><br></b></p>
<p class=""><b><span class="">extension</span><span class=""> </span><span class="">CGFloat</span><span class=""> {</span></b></p>
<p class=""><span class=""><b> </b></span></p>
<p class=""><b><span class=""> </span><span class="">init</span><span class=""><T: </span><span class="">Box</span><span class=""> </span><span class="">where</span><span class=""> </span><span class="">T</span><span class="">.</span><span class="">BoxType</span><span class=""> == </span><span class="">Double</span><span class=""> >(</span><span class="">_</span><span class=""> box: </span><span class="">T</span><span class="">) {</span></b></p>
<p class=""><b><span class=""> </span><span class="">self</span><span class="">.</span><span class="">init</span><span class="">(box.</span><span class="">value</span><span class="">)</span></b></p>
<p class=""><span class=""><b> }</b></span></p>
<p class=""><span class=""><b> </b></span></p>
<p class=""><b><span class=""> </span><span class="">init</span><span class=""><T: </span><span class="">Box</span><span class=""> </span><span class="">where</span><span class=""> </span><span class="">T</span><span class="">.</span><span class="">BoxType</span><span class=""> == </span><span class="">Int</span><span class=""> >(</span><span class="">_</span><span class=""> box: </span><span class="">T</span><span class="">) {</span></b></p>
<p class=""><b><span class=""> </span><span class="">self</span><span class="">.</span><span class="">init</span><span class="">(box.</span><span class="">value</span><span class="">)</span></b></p>
<p class=""><span class=""><b> }</b></span></p>
<p class=""><span class=""><b>}</b></span></p>
<p class=""><b><span class=""></span><br></b></p>
<p class=""><span class=""><b>//Adding FloatLiteralConvertible, IntegerLiteralConvertible</b></span></p>
<p class=""><b><span class=""></span><br></b></p>
<p class=""><b><span class="">extension</span><span class=""> </span><span class="">FloatingPointBox</span><span class=""> </span><span class="">where</span><span class=""> </span><span class="">Self</span><span class="">.BoxType == Double, </span><span class="">Self</span><span class="">.FloatLiteralConvertible == Double {</span></b></p>
<p class=""><span class=""><b> </b></span></p>
<p class=""><b><span class=""> </span><span class="">init</span><span class="">(floatLiteral value: </span><span class="">Double</span><span class="">) {</span></b></p>
<p class=""><b><span class=""> </span><span class="">self</span><span class="">.</span><span class="">init</span><span class="">(value)</span></b></p>
<p class=""><span class=""><b> }</b></span></p>
<p class=""><span class=""><b> </b></span></p>
<p class=""><b><span class=""> </span><span class="">init</span><span class="">(integerLiteral value: </span><span class="">Int</span><span class="">) {</span></b></p>
<p class=""><b><span class=""> </span><span class="">self</span><span class="">.</span><span class="">init</span><span class="">(value)</span></b></p>
<p class=""><span class=""><b> }</b></span></p>
<p class=""><span class=""><b> </b></span></p>
<p class=""><b><span class=""> </span><span class="">init</span><span class=""><T: </span><span class="">IntegerType</span><span class="">>(</span><span class="">_</span><span class=""> value: </span><span class="">T</span><span class="">) {</span></b></p>
<p class=""><b><span class=""> </span><span class="">self</span><span class="">.</span><span class="">init</span><span class="">(value)</span></b></p>
<p class=""><span class=""><b> }</b></span></p>
<p class=""><span class=""><b>}</b></span></p></div><div><br></div><div>Here is my example of using the Box protocol:</div><div>
<p class=""><b><span class="">struct</span><span class=""> Degree: </span><span class="">FloatingPointBox</span><span class=""> {</span></b></p>
<p class=""><span class=""><b> </b></span></p>
<p class=""><b><span class=""> </span><span class="">var</span><span class=""> value: </span><span class="">Double</span><span class=""> = </span><span class="">0</span></b></p>
<p class=""><span class=""><b> </b></span></p>
<p class=""><b><span class=""> </span><span class="">init</span><span class="">()</span></b></p>
<p class=""><span class=""><b> {</b></span></p>
<p class=""><span class=""><b> }</b></span></p>
<p class=""><span class=""><b>}</b></span></p>
<p class=""><b><span class=""></span><br></b></p>
<p class=""><b><span class="">protocol</span><span class=""> DegreeConvertiable {</span></b></p>
<p class=""><span class=""><b> </b></span></p>
<p class=""><b><span class=""> </span><span class="">init</span><span class="">(degreeLiteral value: </span><span class="">Degree</span><span class="">)</span></b></p>
<p class=""><span class=""><b>}</b></span></p>
<p class=""><b><span class=""></span><br></b></p>
<p class=""><b><span class="">extension</span><span class=""> </span><span class="">Degree</span><span class="">: </span><span class="">RadianConvertiable</span><span class=""> {</span></b></p>
<p class=""><span class=""><b> </b></span></p>
<p class=""><b><span class=""> </span><span class="">init</span><span class="">(radianLiteral value: </span><span class="">Radian</span><span class="">) {</span></b></p>
<p class=""><b><span class=""> </span><span class="">self</span><span class="">.</span><span class="">value</span><span class=""> = </span><span class="">Double</span><span class="">(value) * </span><span class="">180.0</span><span class=""> / </span><span class="">M_PI</span></b></p>
<p class=""><span class=""><b> }</b></span></p>
<p class=""><span class=""><b> </b></span></p>
<p class=""><b><span class=""> </span><span class="">init</span><span class="">(</span><span class="">_</span><span class=""> value: </span><span class="">Radian</span><span class="">) {</span></b></p>
<p class=""><b><span class=""> </span><span class="">self</span><span class="">.</span><span class="">init</span><span class="">(radianLiteral: value)</span></b></p>
<p class=""><span class=""><b> }</b></span></p>
<p class=""><span class=""><b>}</b></span></p></div></div><div class="gmail_extra"><br><div class="gmail_quote">On Tue, Jan 5, 2016 at 5:24 PM, Matthew Johnson via swift-evolution <span dir="ltr"><<a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><span class=""><br>
> On Jan 5, 2016, at 11:16 AM, Thorsten Seitz via swift-evolution <<a href="mailto:swift-evolution@swift.org">swift-evolution@swift.org</a>> wrote:<br>
><br>
><br>
>> Am 05.01.2016 um 17:11 schrieb Grzegorz Adam Hankiewicz via swift-evolution <<a href="mailto:swift-evolution@swift.org">swift-evolution@swift.org</a>>:<br>
>><br>
>> The ideal would be for the compiler to pretend Euros or RefTablePk are different types, yet use their parent type at the binary level. This needs a specific syntax to teach the compiler which existing methods/operations are allowed on the new fake types and which aren’t. These new distinct types would *borrow* previous implementations.<br>
><br>
> What about citing the relevant protocols in the newtype definition? This should include the ability to use my own protocols to which I have made the underlying type conform to by an extension.<br>
<br>
</span>This is how my forwarding proposal works. The newtype syntax I suggested as a possible extension looks like this:<br>
<br>
newtype Euro = Double forwarding Addable, Subtractable<br>
<br>
The keyword could be different, but I think `forwarding` is not bad. When I complete the second draft I think it will make even more sense. The forwarding facility has features to handle non-trivial cases (Self and associated type requirements, etc).<br>
<div class="HOEnZb"><div class="h5"><br>
><br>
> Throwing some syntax into the discussion:<br>
><br>
> newtype Euro = Double : Addable, Subtractable<br>
><br>
> where I have defined the protocols Addable and Subtractable somewhere and made Double conform to them if all this is not provided by the standard library.<br>
> The implementation of Euro then borrows the implementation of Double for these protocols.<br>
><br>
> -Thorsten<br>
> _______________________________________________<br>
> swift-evolution mailing list<br>
> <a href="mailto:swift-evolution@swift.org">swift-evolution@swift.org</a><br>
> <a href="https://lists.swift.org/mailman/listinfo/swift-evolution" rel="noreferrer" target="_blank">https://lists.swift.org/mailman/listinfo/swift-evolution</a><br>
<br>
_______________________________________________<br>
swift-evolution mailing list<br>
<a href="mailto:swift-evolution@swift.org">swift-evolution@swift.org</a><br>
<a href="https://lists.swift.org/mailman/listinfo/swift-evolution" rel="noreferrer" target="_blank">https://lists.swift.org/mailman/listinfo/swift-evolution</a><br>
</div></div></blockquote></div><br><br clear="all"><div><br></div>-- <br><div class="gmail_signature"><div dir="ltr"><div><div dir="ltr"><div dir="ltr"><div><span style="font-size:16px;line-height:19.2px"></span><span style="font-size:12.8px"> Wizard</span><br></div><div><a href="mailto:james@supmenow.com" target="_blank">james@supmenow.com</a></div><div>+44 7523 279 698</div></div></div></div></div></div>
</div>