I've been thinking about this, too. At one point I had a reason to want an 
Array that couldn't be empty (though I can't recall what the reason was now).

Anyway, I think I'd do something like this:
struct NonEmptyCollection <T : CollectionType> : CollectionType {
    private var _head: T.Generator.Element? //optional because it needs to have 
a default value in case the init has to fail. Seems like there ought to be a 
work-around that doesn't have the overhead, but I'm drawing a blank.
    var head: T.Generator.Element {
        get { return _head! } //always safe to unwrap because there's no way to 
say `_head = nil` once the init succeeds
        set { _head = newValue }
    }
    var tail: T
    init?(_ c: T) {
        // bail if c is empty
    }
    // whatever else CollectionType needs
}

There's undoubtedly a better way to do it, but I *think* that should work.

HTH,
- Dave Sweeris

> On Jun 25, 2016, at 18:54, Gwynne Raskind via swift-dev <swift-dev@swift.org> 
> wrote:
> 
> I’ve been spinning my wheels on this one for a couple of hours and can’t come 
> up with a way to do it which doesn’t require checking for at least one 
> potential data inconsistency at runtime with precondition() or assert(), so 
> I’m wondering if anyone else has a solution.
> 
> I have a data type which is conceptually a Set (not an OptionSet, it’s not a 
> bitfield and has no concrete representation, simply a Set). This Set may 
> contain members chosen from a limited set of choices, which in Swift I 
> represent as an enum:
> 
> enum Kind {
>    case FirstKind
>    case SecondKind
>    case ThirdKind
> }
> 
> typealias Kinds = Set<Kind>
> 
> The data to which this applies is a structure-
> 
> struct DataItem {
>    let kinds: Kinds
>    // other fields
> }
> 
> This structure demands that the Kinds set must always contain at *least* one 
> element, because conceptually "no kind" is not a sensible state for a data 
> item. However, I can’t use just the enum because the data can be of more than 
> one kind at a time. It can just never be of no kinds - in that case, there is 
> no data at all, and I don’t need a state *within* the data to represent that, 
> I would simply have no DataItem in the collection which holds the list of 
> data items.
> 
> In a relational dataset, I would say that the "no kind" state was 
> denormalized, because it can be represented by there being no row in a table. 
> The other obvious alternative, to duplicate the DataItem for each Kind, is 
> also denormalized (multiple rows whose data is not solely defined by the 
> candidate keys). The less obvious alternative of having a map of [Kind : 
> [DataItem]] (in a database this would be akin to having a kindID column in 
> the DataItem table with a separate Kinds lookup table), while fully 
> normalized, is not only inefficient and difficult to manipulate but also 
> disassociates a critical piece of information about the item from the item 
> itself. My in-memory data model is not a relational database.
> 
> Half-digression into relational theory aside, I can’t figure a way to make 
> the compiler enforce this. An enum is "exactly one", a Set is "zero or more", 
> a structure or class is "this group", an Optional is "zero or one". 
> Obviously, I can do "precondition(kinds.count > 0)" to check this at runtime, 
> but that admits that the data can exist in an inconsistent state. Is there 
> some way, even a hacky one, to express in the data model itself (such that 
> the compiler will enforce it) that there must be at least one "kind", as the 
> enum already does for "only one at a time"?
> 
> There’s probably some bit of type theory which explains why this is either 
> difficult or impossible in practice, but I’m hoping maybe it’s just a corner 
> of knowledge I’ve yet to previously delve.
> 
> -- Gwynne Raskind
> 
> 
> 
> _______________________________________________
> swift-dev mailing list
> swift-dev@swift.org
> https://lists.swift.org/mailman/listinfo/swift-dev
_______________________________________________
swift-dev mailing list
swift-dev@swift.org
https://lists.swift.org/mailman/listinfo/swift-dev

Reply via email to