where clauses on enum cases


(Rex) #1

I've run into a problem recently when using generics with enums where I'm
required to specify the type for a generic that isn't used for the enum
case that's constructed.

Example:

protocol Mapping {
    associatedtype Destination
}

enum EvictionPolicy {
    case append
    case replace
}

enum Map<T: Mapping, U: Mapping> where U.Destination: Collection {
    case object(T)
    case collection(U, EvictionPolicy)
}

class IntMapping: Mapping {
    typealias Destination = Int
}

class IntsMapping: Mapping {
    typealias Destination = [Int]
}

// Must specify types for generics that are not in use
let o = Map<IntMapping, IntsMapping>.object(IntMapping())
let c = Map<IntMapping, IntsMapping>.collection(IntsMapping(),
EvictionPolicy.append)

What I'd like to be able to do is the following

enum Map<T: Mapping> {
    case object(T)
    case collection(T, EvictionPolicy) where T.Destination: Collection
}

Could this be added to the language?

···

--

Rex Fenley | IOS DEVELOPER

Remind.com <https://www.remind.com/> | BLOG <http://blog.remind.com/>
> FOLLOW
US <https://twitter.com/remindhq> | LIKE US
<https://www.facebook.com/remindhq>


(Slava Pestov) #2

You’re asking for GADTs: https://en.wikipedia.org/wiki/Generalized_algebraic_data_type

This feature is difficult to implement correctly and efficiently and I doubt Swift will ever support it, but you never know…

Slava

···

On Mar 14, 2017, at 12:44 PM, Rex Fenley via swift-evolution <swift-evolution@swift.org> wrote:

I've run into a problem recently when using generics with enums where I'm required to specify the type for a generic that isn't used for the enum case that's constructed.

Example:

protocol Mapping {
    associatedtype Destination
}

enum EvictionPolicy {
    case append
    case replace
}

enum Map<T: Mapping, U: Mapping> where U.Destination: Collection {
    case object(T)
    case collection(U, EvictionPolicy)
}

class IntMapping: Mapping {
    typealias Destination = Int
}

class IntsMapping: Mapping {
    typealias Destination = [Int]
}

// Must specify types for generics that are not in use
let o = Map<IntMapping, IntsMapping>.object(IntMapping())
let c = Map<IntMapping, IntsMapping>.collection(IntsMapping(), EvictionPolicy.append)

What I'd like to be able to do is the following

enum Map<T: Mapping> {
    case object(T)
    case collection(T, EvictionPolicy) where T.Destination: Collection
}

Could this be added to the language?

--
Rex Fenley | IOS DEVELOPER

Remind.com <https://www.remind.com/> | BLOG <http://blog.remind.com/> | FOLLOW US <https://twitter.com/remindhq> | LIKE US <https://www.facebook.com/remindhq>_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


(Joe Groff) #3

We'll already have most of the same problems with existentials, so I don't think it's unreasonable to support this at some point in the future. Not necessarily the *near* future, of course.

-Joe

···

On Mar 14, 2017, at 12:58 PM, Slava Pestov via swift-evolution <swift-evolution@swift.org> wrote:

You’re asking for GADTs: https://en.wikipedia.org/wiki/Generalized_algebraic_data_type

This feature is difficult to implement correctly and efficiently and I doubt Swift will ever support it, but you never know…