[swift-evolution] Support for newtype feature/typesafe calculations
James Campbell
james at supmenow.com
Wed Jan 6 11:15:52 CST 2016
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 <
swift-evolution at swift.org> wrote:
>
> > On Jan 5, 2016, at 11:16 AM, Thorsten Seitz via swift-evolution <
> swift-evolution at swift.org> wrote:
> >
> >
> >> Am 05.01.2016 um 17:11 schrieb Grzegorz Adam Hankiewicz via
> swift-evolution <swift-evolution at swift.org>:
> >>
> >> 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
> > swift-evolution at swift.org
> > https://lists.swift.org/mailman/listinfo/swift-evolution
>
> _______________________________________________
> swift-evolution mailing list
> swift-evolution at swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution
>
--
Wizard
james at supmenow.com
+44 7523 279 698
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20160106/ef1371cf/attachment-0001.html>
More information about the swift-evolution
mailing list