I've managed to implement this already in the language with a few ugly corners due to the lack of generic protocols.
I created a protocol based on Box (https://github.com/robrix/Box/) which works really well. I have extended this to handle certain special protocols like Equatable so you can do SpecialType == SpecialType, and even literalConversion. There is however a lot of boilerplate: - You have to declare all of your Convertible protocols for converting from one type to another - You have to define an empty init so the protocol extensions have something to chain to. - You need to write the value property with type. 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 :). With member-wise initializations and generic protocols this could be achievable just by adding a Box protocol to the standard library. Here is my implementation of Box as a protocol: *protocol Box: CustomStringConvertible, CustomDebugStringConvertible {* * typealias FloatLiteralType = Double* * typealias IntegerLiteralType = Int* * typealias BoxType = Any* * var value: BoxType { get set }* * init()* * init(_ value: BoxType)* *}* *extension Box where BoxType: CustomStringConvertible {* * var description: String {* * return self.value.description* * }* * var debugDescription: String {* * return "\(self.value.description)㎭"* * }* *}* *//MARK: FloatingPointBox* *protocol FloatingPointBox: Box, FloatLiteralConvertible, IntegerLiteralConvertible {* * typealias BoxType = Double* * typealias FloatLiteralConvertible = Double* * typealias IntegerLiteralConvertible = Int* *}* *extension Box where Self.BoxType == Double {* * init(_ value: Double) {* * self.init()* * self.value = value* * }* * init(_ value: Int) {* * self.init()* * self.value = Double(value)* * }* *}* *extension FloatLiteralType {* * init<T: Box where T.BoxType == Double >(_ box: T) {* * self.init(box.value)* * }* * init<T: Box where T.BoxType == Int >(_ box: T) {* * self.init(box.value)* * }* *}* *extension CGFloat {* * init<T: Box where T.BoxType == Double >(_ box: T) {* * self.init(box.value)* * }* * init<T: Box where T.BoxType == Int >(_ box: T) {* * self.init(box.value)* * }* *}* *//Adding FloatLiteralConvertible, IntegerLiteralConvertible* *extension FloatingPointBox where Self.BoxType == Double, Self.FloatLiteralConvertible == Double {* * init(floatLiteral value: Double) {* * self.init(value)* * }* * init(integerLiteral value: Int) {* * self.init(value)* * }* * init<T: IntegerType>(_ value: T) {* * self.init(value)* * }* *}* Here is my example of using the Box protocol: *struct Degree: FloatingPointBox {* * var value: Double = 0* * init()* * {* * }* *}* *protocol DegreeConvertiable {* * init(degreeLiteral value: Degree)* *}* *extension Degree: RadianConvertiable {* * init(radianLiteral value: Radian) {* * self.value = Double(value) * 180.0 / M_PI* * }* * init(_ value: Radian) {* * self.init(radianLiteral: value)* * }* *}* On Tue, Jan 5, 2016 at 5:24 PM, Matthew Johnson via swift-evolution < [email protected]> wrote: > > > On Jan 5, 2016, at 11:16 AM, Thorsten Seitz via swift-evolution < > [email protected]> wrote: > > > > > >> Am 05.01.2016 um 17:11 schrieb Grzegorz Adam Hankiewicz via > swift-evolution <[email protected]>: > >> > >> 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. > > > > 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. > > This is how my forwarding proposal works. The newtype syntax I suggested > as a possible extension looks like this: > > newtype Euro = Double forwarding Addable, Subtractable > > 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). > > > > > Throwing some syntax into the discussion: > > > > newtype Euro = Double : Addable, Subtractable > > > > 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. > > The implementation of Euro then borrows the implementation of Double for > these protocols. > > > > -Thorsten > > _______________________________________________ > > swift-evolution mailing list > > [email protected] > > https://lists.swift.org/mailman/listinfo/swift-evolution > > _______________________________________________ > swift-evolution mailing list > [email protected] > https://lists.swift.org/mailman/listinfo/swift-evolution > -- Wizard [email protected] +44 7523 279 698
_______________________________________________ swift-evolution mailing list [email protected] https://lists.swift.org/mailman/listinfo/swift-evolution
