Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Enum case with associated value of generic type with constraints

Is there a way, using generics and type constraints, to collapse the first two cases of this enum into one?

enum AllowedValueRange {

    // Associated value represents (min, max). 'nil' represents
    // "no limit" for that interval end (+/- infinity)
    case IntegerRange(Int?, Int?)


    // Associated value represents (min, max). 'nil' represents
    // "no limit" for that interval end (+/- infinity)
    case FloatRange(Float?, Float?)


    // A finite set of specific values of any type
    case ArbitrarySet([Any])

    // (...Other cases with different structure of associated values
    // or no associated values...)
}

Addendum: I know I can specify a generic type for the whole enum, but only these two types need one. Also, I think it needs to conform to both Equatable and Comparable, but I can't quite find the syntax to specify that...


EDIT: It turns out Comparable contains Equatable (?), so perhaps I can do this:

enum AllowedValueRange {

    // Associated value represents (min, max). 'nil' represents
    // "no limit" for that interval end (+/- infinity)
    case NumericRange((min:Comparable?, max:Comparable?))

    // (rest omitted)

(Also switched pair of associated values with single, named tuple of two values)

like image 229
Nicolas Miari Avatar asked Dec 03 '15 07:12

Nicolas Miari


1 Answers

You could define

enum AllowedValueRange {
    case NumericRange((min:Comparable?, max:Comparable?))
}

but that would allow you to instantiate a value with two unrelated comparable types, for example

let range = AllowedValueRange.NumericRange((min: 12, max: "foo"))

which is probably not what you want. So you need a generic type (which is restricted to be comparable):

enum AllowedValueRange<T: Comparable> {
    case NumericRange((min:T?, max:T?))
}
like image 84
Martin R Avatar answered Oct 23 '22 08:10

Martin R