Proposal: newtype feature for creating brand new types from existing types


#1

//Existing typealias feature.//Foo acts exactly the same way as Double. It's
the same thing.//Double can be used instead of Foo anywhere.typealias Foo =
Double
//Proposed newtype feature.//Bar acts exactly the same way as Double and is
the same//thing behind the scenes (until we extend it; see below).//Trying to
use Double instead of Bar will result in a compile-time error.newtype Bar =
Double
Of course, after creating Bar - a "copy" of the type Double, so to speak - I
can extend Bar independenly of Double as one would expect.
This would be highly useful.
Your thoughts?


Newtype without automatic protocol forwarding
#2

Considering the number of times I’ve read about this topic in other languages, I must agree :slight_smile:

Yet there are two difficulties:

First, what does Bar get from Double ?

When you say "after creating Bar, I can extend Bar independenly of Double", the problem lies in the meaning of "after". In a language like Ruby, there is an "after", but there is no such clear thing in Swift: modules/packages are compiled as a whole, and module A can extend a type defined the the module B.

More, let’s see what happens below:

1 let d: Double = 1.0
2 let b: Bar = d // Compiler error, I presume.
3 let b: Bar = Bar(d) // Mandatory so that Bar can be put to any use
4 let b: Bar = 1.0

That point 4 is tricky.

If it is not an error, then 2. should succeed as well, don’t you think?
If it is an error, then one may want to add FloatLiteralConvertible to Bar. Oops, Double already implements it.

Hm. I’m afraid I haven’t found the solution :slight_smile:

Gwendal Roué

···

Le 11 déc. 2015 à 21:09, Tuur Anton via swift-evolution <swift-evolution@swift.org> a écrit :

//Existing typealias feature.
//Foo acts exactly the same way as Double. It's the same thing.
//Double can be used instead of Foo anywhere.
typealias Foo = Double

//Proposed newtype feature.
//Bar acts exactly the same way as Double and is the same
//thing behind the scenes (until we extend it; see below).
//Trying to use Double instead of Bar will result in a compile-time error.
newtype Bar = Double

Of course, after creating Bar - a "copy" of the type Double, so to speak - I can extend Bar independenly of Double as one would expect.

This would be highly useful.

Your thoughts?

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


(Alejandro Martinez) #3

A similar thing has been already mentioned in the list.
I can remember the topic "[swift-evolution] protocol based invocation forwarding" which could resolve in a similar feature.
As I said in there I would be really interested to see this in the language as will allow us to be more type safe with types that are commonly described as strings or numbers, but that are more than that.
Cheers,

···

El 11 dic 2015, a las 20:30, Gwendal Roué via swift-evolution <swift-evolution@swift.org> escribió:

Considering the number of times I’ve read about this topic in other languages, I must agree :slight_smile:

Yet there are two difficulties:

First, what does Bar get from Double ?

When you say "after creating Bar, I can extend Bar independenly of Double", the problem lies in the meaning of "after". In a language like Ruby, there is an "after", but there is no such clear thing in Swift: modules/packages are compiled as a whole, and module A can extend a type defined the the module B.

More, let’s see what happens below:

1 let d: Double = 1.0
2 let b: Bar = d // Compiler error, I presume.
3 let b: Bar = Bar(d) // Mandatory so that Bar can be put to any use
4 let b: Bar = 1.0

That point 4 is tricky.

If it is not an error, then 2. should succeed as well, don’t you think?
If it is an error, then one may want to add FloatLiteralConvertible to Bar. Oops, Double already implements it.

Hm. I’m afraid I haven’t found the solution :slight_smile:

Gwendal Roué

Le 11 déc. 2015 à 21:09, Tuur Anton via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> a écrit :

//Existing typealias feature.
//Foo acts exactly the same way as Double. It's the same thing.
//Double can be used instead of Foo anywhere.
typealias Foo = Double

//Proposed newtype feature.
//Bar acts exactly the same way as Double and is the same
//thing behind the scenes (until we extend it; see below).
//Trying to use Double instead of Bar will result in a compile-time error.
newtype Bar = Double

Of course, after creating Bar - a "copy" of the type Double, so to speak - I can extend Bar independenly of Double as one would expect.

This would be highly useful.

Your thoughts?

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


(Nicky Gerritsen) #4

Considering the number of times I’ve read about this topic in other languages, I must agree :slight_smile:

Yet there are two difficulties:

First, what does Bar get from Double ?

When you say "after creating Bar, I can extend Bar independenly of Double", the problem lies in the meaning of "after". In a language like Ruby, there is an "after", but there is no such clear thing in Swift: modules/packages are compiled as a whole, and module A can extend a type defined the the module B.

More, let’s see what happens below:

1 let d: Double = 1.0
2 let b: Bar = d // Compiler error, I presume.
3 let b: Bar = Bar(d) // Mandatory so that Bar can be put to any use
4 let b: Bar = 1.0

That point 4 is tricky.

If it is not an error, then 2. should succeed as well, don’t you think?
If it is an error, then one may want to add FloatLiteralConvertible to Bar. Oops, Double already implements it.

But that is not true. Take this example:

let x: Int = 3 // Type added for clarity
let y: Double = x // error
let z: Double = 3 // ok

This is exactly why it is Float_Literal_Convertible, it can only convert literals ;).

Anyway, about the general thing: isn’t this just inheritance, but then for struct types?
i.e.

struct Bar : Double {}

— Nicky

···

On 11 dec. 2015, at 21:30, Gwendal Roué via swift-evolution <swift-evolution@swift.org> wrote:

Hm. I’m afraid I haven’t found the solution :slight_smile:

Gwendal Roué

Le 11 déc. 2015 à 21:09, Tuur Anton via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> a écrit :

//Existing typealias feature.
//Foo acts exactly the same way as Double. It's the same thing.
//Double can be used instead of Foo anywhere.
typealias Foo = Double

//Proposed newtype feature.
//Bar acts exactly the same way as Double and is the same
//thing behind the scenes (until we extend it; see below).
//Trying to use Double instead of Bar will result in a compile-time error.
newtype Bar = Double

Of course, after creating Bar - a "copy" of the type Double, so to speak - I can extend Bar independenly of Double as one would expect.

This would be highly useful.

Your thoughts?

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


(Russ Bishop) #5

My assumption is that the proposed newtype simply adopts the storage and
any available functions, operators, and extensions available on the
original type.

Extensions on Double are available to Double and Bar. Extensions explicitly
on Bar are only available on Bar.

That said, I'm not sure this is worth the complexity when you can just wrap
a Double inside your own struct Bar {} and get most of the benefits.

Russ Bishop
russbishop.net

···

On Fri, Dec 11, 2015 at 12:30 PM, Gwendal Roué <swift-evolution@swift.org> wrote:

Considering the number of times I’ve read about this topic in other
languages, I must agree :slight_smile:

Yet there are two difficulties:

First, what does Bar get from Double ?

When you say "after creating Bar, I can extend Bar independenly of
Double", the problem lies in the meaning of "after". In a language like
Ruby, there is an "after", but there is no such clear thing in Swift:
modules/packages are compiled as a whole, and module A can extend a type
defined the the module B.

More, let’s see what happens below:

1 let d: Double = 1.0
2 let b: Bar = d // Compiler error, I presume.
3 let b: Bar = Bar(d) // Mandatory so that Bar can be put to any use
4 let b: Bar = 1.0

That point 4 is tricky.

If it is not an error, then 2. should succeed as well, don’t you think?
If it is an error, then one may want to add FloatLiteralConvertible to
Bar. Oops, Double already implements it.

Hm. I’m afraid I haven’t found the solution :slight_smile:

Gwendal Roué

Le 11 déc. 2015 à 21:09, Tuur Anton via swift-evolution < > swift-evolution@swift.org> a écrit :

//Existing typealias feature.
//Foo acts exactly the same way as Double. It's the same thing.
//Double can be used instead of Foo anywhere.
typealias Foo = Double

//Proposed newtype feature.
//Bar acts exactly the same way as Double and is the same
//thing behind the scenes (until we extend it; see below).
//Trying to use Double instead of Bar will result in a compile-time error.
newtype Bar = Double

Of course, after creating Bar - a "copy" of the type Double, so to speak -
I can extend Bar independenly of Double as one would expect.

This would be highly useful.

Your thoughts?
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


(Alejandro Martinez) #6

Anyway, about the general thing: isn’t this just inheritance, but then for struct types?
i.e.

struct Bar : Double {}

Not exactly as inheritance will let you use Bar in any place where do you expect Double.
Presumably newtype does not.

···

El 11 dic 2015, a las 20:34, Nicky Gerritsen via swift-evolution <swift-evolution@swift.org> escribió:

On 11 dec. 2015, at 21:30, Gwendal Roué via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

Considering the number of times I’ve read about this topic in other languages, I must agree :slight_smile:

Yet there are two difficulties:

First, what does Bar get from Double ?

When you say "after creating Bar, I can extend Bar independenly of Double", the problem lies in the meaning of "after". In a language like Ruby, there is an "after", but there is no such clear thing in Swift: modules/packages are compiled as a whole, and module A can extend a type defined the the module B.

More, let’s see what happens below:

1 let d: Double = 1.0
2 let b: Bar = d // Compiler error, I presume.
3 let b: Bar = Bar(d) // Mandatory so that Bar can be put to any use
4 let b: Bar = 1.0

That point 4 is tricky.

If it is not an error, then 2. should succeed as well, don’t you think?
If it is an error, then one may want to add FloatLiteralConvertible to Bar. Oops, Double already implements it.

But that is not true. Take this example:

let x: Int = 3 // Type added for clarity
let y: Double = x // error
let z: Double = 3 // ok

This is exactly why it is Float_Literal_Convertible, it can only convert literals ;).

Anyway, about the general thing: isn’t this just inheritance, but then for struct types?
i.e.

struct Bar : Double {}

— Nicky

Hm. I’m afraid I haven’t found the solution :slight_smile:

Gwendal Roué

Le 11 déc. 2015 à 21:09, Tuur Anton via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> a écrit :

//Existing typealias feature.
//Foo acts exactly the same way as Double. It's the same thing.
//Double can be used instead of Foo anywhere.
typealias Foo = Double

//Proposed newtype feature.
//Bar acts exactly the same way as Double and is the same
//thing behind the scenes (until we extend it; see below).
//Trying to use Double instead of Bar will result in a compile-time error.
newtype Bar = Double

Of course, after creating Bar - a "copy" of the type Double, so to speak - I can extend Bar independenly of Double as one would expect.

This would be highly useful.

Your thoughts?

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution