Type alias with a "where" clause specifying required associated type

I have the following ProceduralDrawing type:

public struct ProceduralDrawing<Float, Point: PointType> where Point.Float == Float {
    // ... code that used Float and Point ...
}

public protocol PointType {
    associatedtype Float: FloatingPoint
    var x: Float { get }
    var y: Float { get }
}

I would like to avoid adding Point as a generic parameter but the following doesn’t work:

public struct ProceduralDrawing<Float: FloatingPoint> {
    // ERROR: 'where' clause cannot be attached to a non-generic declaration
    typealias Point = PointType where Point.Float == Float
    // ... code that uses Float and Point ...
}

Is there a way to do this? If not, why?

Thanks!

R+

1 Like

Hi Rudolf,

What you are describing is not possible right now. The protocol PointType cannot be used as a type at all, because it has an associated type requirement. Also it is not clear what a ‘where’ clause attached to a type alias would mean.

There has been some discussion of ‘generalized existentials’ on the evolution list. So eventually, you might be able to say something like this:

typealias Point = Any<Point : PointType where Point.Float == Float>

Slava

···

On Sep 4, 2017, at 6:12 PM, Rudolf Adamkovič via swift-users <swift-users@swift.org> wrote:

I have the following ProceduralDrawing type:

public struct ProceduralDrawing<Float, Point: PointType> where Point.Float == Float {
    // ... code that used Float and Point ...
}

public protocol PointType {
    associatedtype Float: FloatingPoint
    var x: Float { get }
    var y: Float { get }
}

I would like to avoid adding Point as a generic parameter but the following doesn’t work:

public struct ProceduralDrawing<Float: FloatingPoint> {
    // ERROR: 'where' clause cannot be attached to a non-generic declaration
    typealias Point = PointType where Point.Float == Float
    // ... code that uses Float and Point ...
}

Is there a way to do this? If not, why?

Thanks!

R+
_______________________________________________
swift-users mailing list
swift-users@swift.org
https://lists.swift.org/mailman/listinfo/swift-users

I see. TBH, I don’t understand why it says “Any” in the "generalized existentials” but everything else is clear.

Thank you Slava!

R+

···

On 5 Sep 2017, at 01:52, Slava Pestov <spestov@apple.com> wrote:

Hi Rudolf,

What you are describing is not possible right now. The protocol PointType cannot be used as a type at all, because it has an associated type requirement. Also it is not clear what a ‘where’ clause attached to a type alias would mean.

There has been some discussion of ‘generalized existentials’ on the evolution list. So eventually, you might be able to say something like this:

typealias Point = Any<Point : PointType where Point.Float == Float>

Slava

On Sep 4, 2017, at 6:12 PM, Rudolf Adamkovič via swift-users <swift-users@swift.org <mailto:swift-users@swift.org>> wrote:

I have the following ProceduralDrawing type:

public struct ProceduralDrawing<Float, Point: PointType> where Point.Float == Float {
    // ... code that used Float and Point ...
}

public protocol PointType {
    associatedtype Float: FloatingPoint
    var x: Float { get }
    var y: Float { get }
}

I would like to avoid adding Point as a generic parameter but the following doesn’t work:

public struct ProceduralDrawing<Float: FloatingPoint> {
    // ERROR: 'where' clause cannot be attached to a non-generic declaration
    typealias Point = PointType where Point.Float == Float
    // ... code that uses Float and Point ...
}

Is there a way to do this? If not, why?

Thanks!

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

It’s just placeholder syntax for ‘a value whose type is given by a generic parameter in the following signature’.

Slava

···

On Sep 5, 2017, at 4:44 AM, Rudolf Adamkovič <salutis@me.com> wrote:

I see. TBH, I don’t understand why it says “Any” in the "generalized existentials” but everything else is clear.

Thank you Slava!

R+

On 5 Sep 2017, at 01:52, Slava Pestov <spestov@apple.com <mailto:spestov@apple.com>> wrote:

Hi Rudolf,

What you are describing is not possible right now. The protocol PointType cannot be used as a type at all, because it has an associated type requirement. Also it is not clear what a ‘where’ clause attached to a type alias would mean.

There has been some discussion of ‘generalized existentials’ on the evolution list. So eventually, you might be able to say something like this:

typealias Point = Any<Point : PointType where Point.Float == Float>

Slava

On Sep 4, 2017, at 6:12 PM, Rudolf Adamkovič via swift-users <swift-users@swift.org <mailto:swift-users@swift.org>> wrote:

I have the following ProceduralDrawing type:

public struct ProceduralDrawing<Float, Point: PointType> where Point.Float == Float {
    // ... code that used Float and Point ...
}

public protocol PointType {
    associatedtype Float: FloatingPoint
    var x: Float { get }
    var y: Float { get }
}

I would like to avoid adding Point as a generic parameter but the following doesn’t work:

public struct ProceduralDrawing<Float: FloatingPoint> {
    // ERROR: 'where' clause cannot be attached to a non-generic declaration
    typealias Point = PointType where Point.Float == Float
    // ... code that uses Float and Point ...
}

Is there a way to do this? If not, why?

Thanks!

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

Bump. Any update on this?
I would really like to do something like:

typealias StringEnum = RawRepresentable where StringEnum.RawValue == String
1 Like

Instead of a typealias, I'm using a protocol for StringRepresentable, as follows:

protocol StringRepresentable: RawRepresentable, Codable, Hashable where RawValue == String {}

I'm including Codable and Hashable here for free functionality.

StringRepresentable can then be used on enums like so:

enum AttributeKey: String, StringRepresentable { … }

And on generic types:

struct KeyValuePair<GenericKey: StringRepresentable>: Codable, Hashable {
    var key: GenericKey
    var value: String
}

The introduction of primary associated types in Swift 5.7 makes this particular case easy to express:

typealias StringRepresentable = RawRepresentable<Int>

func foo<T: StringRepresentable>(_: T) {}

StringRepresentable becomes a "constraint type" and can also be used an existential with any, ie any StringRepresentable.

2 Likes