# \[Pitch\] Primary Associated Types in the Standard Library

**URL:** <https://forums.swift.org/t/pitch-primary-associated-types-in-the-standard-library/56426>\
**Category:** Pitches\
**Tags:** generics, protocols, stdlib\
**Created:** [April 1, 2022, 12:31am UTC](https://forums.swift.org/t/pitch-primary-associated-types-in-the-standard-library/56426 "2022-04-01T00:31:19Z")\
**Posts on this page:** 20\
**Page:** 2

<div class="post-metadata">

**Author:** ![benrimmington](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/benrimmington/32/695_2.png) [@benrimmington](https://forums.swift.org/u/benrimmington)\
**Post date:** [April 2, 2022, 1:52am UTC](https://forums.swift.org/t/pitch-primary-associated-types-in-the-standard-library/56426/21 "2022-04-02T01:52:18Z")

</div>

> [@lorentey](#):
>
> I updated the table accordingly.

Corrections for the "Others" column:

- `SetAlgebra` inherits `ArrayLiteralElement`.

- `OptionSet` inherits `ArrayLiteralElement` and `RawValue`.

- `FloatingPoint` inherits `Stride`.

- `BinaryFloatingPoint` inherits `Stride`.

---

<div class="post-metadata">

**Author:** ![Philippe\_Hausler](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/philippe_hausler/32/22569_2.png) [@Philippe\_Hausler](https://forums.swift.org/u/Philippe_Hausler)\
**Post date:** [April 2, 2022, 6:28am UTC](https://forums.swift.org/t/pitch-primary-associated-types-in-the-standard-library/56426/22 "2022-04-02T06:28:25Z")

</div>

> [@John\_McCall](#):
>
> I don't know what a generic `Clock` would look like, for example.

Clock does not have a primary associated type imho. Clocks are used upon their behavior not associated types.

---

<div class="post-metadata">

**Author:** ![filip-sakel](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/filip-sakel/32/8697_2.png) [@filip-sakel](https://forums.swift.org/u/filip-sakel)\
**Post date:** [April 2, 2022, 6:29am UTC](https://forums.swift.org/t/pitch-primary-associated-types-in-the-standard-library/56426/23 "2022-04-02T06:29:01Z")

</div>

I wholeheartedly agree. Even if we had generic-parameter labels, which I think are useful for things like default generic parameters, I don’t think they’d be the right fit here.

In fact, tooling support will also be very important. A simple feature that wouldn’t depend on documenting associated types would be to offer an auto completion list similar to that of function overloads when the user types out brackets after a protocol. Then, when the user selects an option, a placeholder with the associated type’s name at will be inserted. This way, intuition will naturally start to develop with users naturally describing their constrained protocols with prepositions. This way of spelling a protocol with primary associated types could also be reflected in the docs. For example, the Identifiable overview is currently:

> A class of types whose instances hold the value of an entity with stable identity.

But it could become:

> A type whose instances hold an entity, that can be identified _by_ that entity’s stable identity.

So I think we can avoid introducing Identifiable\<By: Int\> which would just add verbosity in the long run.

---

<div class="post-metadata">

**Author:** ![ben-cohen](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/ben-cohen/32/296_2.png) [@ben-cohen](https://forums.swift.org/u/ben-cohen)\
**Post date:** [April 2, 2022, 4:58pm UTC](https://forums.swift.org/t/pitch-primary-associated-types-in-the-standard-library/56426/25 "2022-04-02T16:58:29Z")

</div>

Since it is mostly of-topic, I suggest asking this question in a new thread on Evolution/Discussion rather than here.

---

<div class="post-metadata">

**Author:** ![Douglas\_Gregor](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/douglas_gregor/32/1362_2.png) [@Douglas\_Gregor](https://forums.swift.org/u/Douglas_Gregor)\
**Post date:** [April 6, 2022, 12:56am UTC](https://forums.swift.org/t/pitch-primary-associated-types-in-the-standard-library/56426/26 "2022-04-06T00:56:52Z")

</div>

Excited to see this!

> [@lorentey](#):
>
> `LazySequenceProtocol` and `LazyCollectionProtocol` use `Elements` as their primary associated type, not `Element` . The idea here is that if we spell out `LazyCollectionProtocol` , we probably want to also say something about the wrapped collection, not just its element type -- for example, by constraining it to random access collections using `some LazyCollectionProtocol<some RandomAccessCollection<String>>` .

Personally, I'd rather we not add any primary associated types to `LazySequenceProtocol` and `LazyCollectionProtocol`. They aren't likely to be used often, and it feels odd to have them be based on `Elements` rather than `Element` like the other sequence/collection protocols. We could always add them later if compelling use cases show up in sufficient quantity.

> [@lorentey](#):
>
> Feedback would be most appreciated -- did I miss anything?

The distributed actors [runtime](https://github.com/apple/swift-evolution/blob/main/proposals/0344-distributed-actor-runtime.md) proposal added a few protocols that could benefit from this feature. @ktoso should weigh in here as well, but my take is:

- `DistributedActor<ActorSystem>`
- `DistributedActorSystem<SerializationRequirement>`: this protocol has several associated types, but I anticipate `any DistributedActorSystem<Codable>` to be a Very Useful Thing.
- `DistributedTargetInvocationEncoder<SerializationRequirement>`
- `DistributedTargetInvocationDecoder<SerializationRequirement>`
- `DistributedTargetInvocationResultHandler<SerializationRequirement>`

> [@lorentey](#):
>
> `AsyncSequence` and `AsyncIteratorProtocol` are intentional omissions -- given that there are ongoing discussions about adding an `Error` type to these, it seems prudent to leave these out until we know more. (Per [SE-0346](https://github.com/apple/swift-evolution/blob/main/proposals/0346-light-weight-same-type-syntax.md), adding `Error` as a second primary would be a source-breaking change.)

Definitely the right call. We should bring this in when we've dealt with the `Error` type, rethrowing conformances, and all of the other exciting throwing-ness of these protocols.

Doug

---

<div class="post-metadata">

**Author:** ![ktoso](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/ktoso/32/44526_2.png) [@ktoso](https://forums.swift.org/u/ktoso)\
**Post date:** [April 6, 2022, 1:35am UTC](https://forums.swift.org/t/pitch-primary-associated-types-in-the-standard-library/56426/27 "2022-04-06T01:35:32Z")

</div>

Thanks for the ping @Douglas_Gregor! I had skimmed this proposal and work but somehow didn't connect the dots all the way.

> [@Douglas\_Gregor](#):
>
> > [@lorentey](#):
> >
> > Feedback would be most appreciated -- did I miss anything?
> 
> The distributed actors [runtime](https://github.com/apple/swift-evolution/blob/main/proposals/0344-distributed-actor-runtime.md) proposal added a few protocols that could benefit from this feature. @ktoso should weigh in here as well, but my take is:
> 
> - `DistributedActor<ActorSystem>`
> - `DistributedActorSystem<SerializationRequirement>` : this protocol has several associated types, but I anticipate `any DistributedActorSystem<Codable>` to be a Very Useful Thing.
> - `DistributedTargetInvocationEncoder<SerializationRequirement>`
> - `DistributedTargetInvocationDecoder<SerializationRequirement>`
> - `DistributedTargetInvocationResultHandler<SerializationRequirement>`

Yes, those look exactly right! 💯

The two "visible by users" protocols especially will benefit _a ton_ from this, because right now half of the methods on the cluster have to be annotated with actor system requirements like this:

```swift
    public func termination<Watchee>(
        of watchee: Watchee,
        ...
    ) where Watchee: DistributedActor, Watchee.ActorSystem == ClusterSystem {

```

which is very annoying and also makes it tricky to store them. With primary associated types this'll be:

```swift
  public func termination<Watchee>(
        of watchee: Watchee,
        ...
    ) where Watchee: DistributedActor<ClusterSystem> {

```

or maybe just `any DistributedActor<ClusterSystem>` in some places...

The `DistributedActorSystem` indeed has many associated types, but the only ones which matter to outside users are:

- `SerializationRequirement` - the type arguments are checked for
- `ActorID` -- equal to the `DistributedActor.ID` that it assigns

The `ID` isn't really all that interesting when passing around a system as `any DistributedActorSystem` I think, and we can always use where clauses if so. But the `any DistributedActorSystem<Codable>` seems to be the most useful...

**Summary:**

- the list Doug provided seems right and this'll be very useful
  - `DistributedActor<ActorSystem>` (implies `DistributedActor.ID` as well)
  - system implementation internal protocols:
  - `DistributedTargetInvocationEncoder<SerializationRequirement>`
  - `DistributedTargetInvocationDecoder<SerializationRequirement>`
  - `DistributedTargetInvocationResultHandler<SerializationRequirement>`

- Pending question:
  - I have to make sure about `DistributedActorSystem` if we need the `ActorID` as primary as well or not...
  - it might simplify mocking out actor systems I think...? Will look into this.

---

<div class="post-metadata">

**Author:** ![jjatie](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/jjatie/32/24428_2.png) [@jjatie](https://forums.swift.org/u/jjatie)\
**Post date:** [April 6, 2022, 7:05am UTC](https://forums.swift.org/t/pitch-primary-associated-types-in-the-standard-library/56426/28 "2022-04-06T07:05:51Z")

</div>

> [@ktoso](#):
>
> With primary associated types this'll be:
> 
> ```swift
> public func termination<Watchee>(
> of watchee: Watchee,
> ...
> ) where Watchee: DistributedActor<ClusterSystem> {
> 
> ```

Why not just?

```swift
public func termination(of watchee: some DistributedActor<ClusterSystem>)

```

Is there some benefit of the (traditional) expanded generics syntax that is desirable to use in core libraries, or was it just habit to reach for it?

---

<div class="post-metadata">

**Author:** ![ktoso](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/ktoso/32/44526_2.png) [@ktoso](https://forums.swift.org/u/ktoso)\
**Post date:** [April 6, 2022, 7:11am UTC](https://forums.swift.org/t/pitch-primary-associated-types-in-the-standard-library/56426/29 "2022-04-06T07:11:06Z")

</div>

Out of habit here, not for some specific reason, not yet used to the new `some`/`any` syntaxes available -- I'll give it all a proper look and I think we'll include the distributed type amendments in this proposal as Karoy intends to propose it for review soon 🙂

---

<div class="post-metadata">

**Author:** ![stephencelis](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/stephencelis/32/2675_2.png) [@stephencelis](https://forums.swift.org/u/stephencelis)\
**Post date:** [April 6, 2022, 10:31pm UTC](https://forums.swift.org/t/pitch-primary-associated-types-in-the-standard-library/56426/30 "2022-04-06T22:31:24Z")

</div>

> [@Philippe\_Hausler](#):
>
> Clock does not have a primary associated type imho. Clocks are used upon their behavior not associated types.

Interacting with a clock seems to require knowledge of its `Instant.Duration`, right? Otherwise you have no way of referring to an advanced instant, or how to tell it to `sleep` to a certain instant.

So it sounds appropriate for `Clock`'s primary associated type to be this associated type of its `Instant`. Similar to how `Collection<Element>` shares its primary associated type with its `Iterator`.

Having `Clock<Duration>` would allow you to tell an arbitrary clock to sleep so long as you know its primary associated type, which is particularly useful for writing testable, time-based code, where your application logic can be injected with `some Clock<Duration>`: it can take a `ContinuousClock` when run in release, and a theoretical `TestClock` that can be manually advanced in your tests.

In [Combine Schedulers](https://github.com/pointfreeco/combine-schedulers) we needed to parameterize a type-erased scheduler ([`AnyScheduler`](https://github.com/pointfreeco/combine-schedulers/blob/84858ad114d8737af5fe58d726d81f15d5b8bd23/Sources/CombineSchedulers/AnyScheduler.swift#L121)) and [`TestScheduler`](https://github.com/pointfreeco/combine-schedulers/blob/84858ad114d8737af5fe58d726d81f15d5b8bd23/Sources/CombineSchedulers/TestScheduler.swift#L58) over the `SchedulerTimeType` in order to inject testable schedulers into application code. It would seem that without a primary associated type on `Clock`, anyone that would want to do something similar would need to still resort to bespoke wrapper types, like `AnyClock`.

---

<div class="post-metadata">

**Author:** ![Philippe\_Hausler](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/philippe_hausler/32/22569_2.png) [@Philippe\_Hausler](https://forums.swift.org/u/Philippe_Hausler)\
**Post date:** [April 6, 2022, 10:36pm UTC](https://forums.swift.org/t/pitch-primary-associated-types-in-the-standard-library/56426/31 "2022-04-06T22:36:33Z")

</div>

I spoke at length about this with @lorentey. I retract the objection that it isn't capable of being a primary type. Instead I have a feeling that will only be needed/wanted in very specific scenarios; more often than not it will be folks using a concrete `Clock` type. There isn't any reason to not do it, only very boutique utility for doing it.

We already have a test clock system setup: [swift-async-algorithms/Clock.swift at main · apple/swift-async-algorithms · GitHub](https://github.com/apple/swift-async-algorithms/blob/main/Sources/AsyncSequenceValidation/Clock.swift). That seems to work pretty darned well for that specific use case; it just means that algorithms should just take generalized clocks if they plan on supporting any clock.

---

<div class="post-metadata">

**Author:** ![stephencelis](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/stephencelis/32/2675_2.png) [@stephencelis](https://forums.swift.org/u/stephencelis)\
**Post date:** [April 6, 2022, 10:45pm UTC](https://forums.swift.org/t/pitch-primary-associated-types-in-the-standard-library/56426/32 "2022-04-06T22:45:46Z")

</div>

> [@Philippe\_Hausler](#):
>
> We already have a test clock system setup: [swift-async-algorithms/Clock.swift at main · apple/swift-async-algorithms · GitHub](https://github.com/apple/swift-async-algorithms/blob/main/Sources/AsyncSequenceValidation/Clock.swift). That seems to work pretty darned well for that specific use case; it just means that algorithms should just take generalized clocks if they plan on supporting any clock.

I took a look at this, but it only seems appropriate for testing small algorithms/operators, and not larger systems that interact with time-based code. As soon as you are operating with a larger system over time (like testing an observable object in a SwiftUI app) it will need to hold onto a clock that is erased in some way.

I understand that testing can often be an afterthought, but by not providing a primary associated type here, anyone that wants to write testable, time-based code for a larger feature will be forced to write a concrete `AnyClock` wrapper.

---

<div class="post-metadata">

**Author:** ![Paulo\_Faria](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/paulo_faria/32/20351_2.png) [@Paulo\_Faria](https://forums.swift.org/u/Paulo_Faria)\
**Post date:** [April 6, 2022, 11:08pm UTC](https://forums.swift.org/t/pitch-primary-associated-types-in-the-standard-library/56426/33 "2022-04-06T23:08:07Z")

</div>

> [@stephencelis](#):
>
> `Clock<Duration>`

+1 for `Clock<Duration>`. 🙂

By the way, the Point Free episode on controlling time in tests is simply amazing @stephencelis. Crème de la crème!

---

<div class="post-metadata">

**Author:** ![Slava\_Pestov](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/slava_pestov/32/30204_2.png) [@Slava\_Pestov](https://forums.swift.org/u/Slava_Pestov)\
**Post date:** [April 7, 2022, 2:20am UTC](https://forums.swift.org/t/pitch-primary-associated-types-in-the-standard-library/56426/34 "2022-04-07T02:20:40Z")

</div>

> [@lorentey](#):
>
> Note that `Unicode.Encoding` and `Unicode.Parser` are considered public protocols that currently happen to be typealiases to underscored protocol definitions, for very annoying technical reasons. (Which we should eventually get around to resolving...)

FWIW, this does work:

```swift
enum Foo {
  typealias Bar = _Foo_Bar
}

protocol _Foo_Bar<T> {
  associatedtype T
}

struct G<X : Foo.Bar<Int>> {}

```

---

<div class="post-metadata">

**Author:** ![lorentey](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/lorentey/32/1299_2.png) [@lorentey](https://forums.swift.org/u/lorentey)\
**Post date:** [April 7, 2022, 3:40am UTC](https://forums.swift.org/t/pitch-primary-associated-types-in-the-standard-library/56426/35 "2022-04-07T03:40:04Z")

</div>

> [@Paulo\_Faria](#):
>
> > [@stephencelis](#):
> >
> > `Clock<Duration>`
> 
> +1 for `Clock<Duration>` . 🙂
> 
> By the way, the Point Free episode on controlling time in tests is simply amazing @stephencelis. Crème de la crème!

`Clock<Duration>` would be a fine choice; unfortunately, `protocol Clock` does not have an associated type called `Duration`. It only has `Instant`.

It may not be too late to introduce one. A similar precedent is `Sequence`, which has an `Element` associated type even though in theory it could just be a typealias for `Iterator.Element`.

---

<div class="post-metadata">

**Author:** ![stephencelis](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/stephencelis/32/2675_2.png) [@stephencelis](https://forums.swift.org/u/stephencelis)\
**Post date:** [April 7, 2022, 3:44am UTC](https://forums.swift.org/t/pitch-primary-associated-types-in-the-standard-library/56426/36 "2022-04-07T03:44:23Z")

</div>

Is there any reason that couldn't be amended? Basically have a similar hierarchy to `Collection`/`Sequence`?

```swift
Collection<Element> where Iterator.Element == Element
Clock<Duration> where Instant.Duration == Duration

```

If not, would your original proposal allow for something like the following?

```swift
any Clock<any Instant<Duration>>

```

I'm not sure I can come up with a reason to parameterize the `Instant` (much like I can't come up with a reason to parameterize `Collection<Iterator>`), but this would at least be an improvement over no primary associated type 🙂

_Edit:_ Saw your update! +1 to the idea of introducing one. It makes more sense to me as a primary type, though I'd love to hear from folks that have use cases for parameterizing over the `Instant` instead.

---

<div class="post-metadata">

**Author:** ![lorentey](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/lorentey/32/1299_2.png) [@lorentey](https://forums.swift.org/u/lorentey)\
**Post date:** [April 7, 2022, 3:48am UTC](https://forums.swift.org/t/pitch-primary-associated-types-in-the-standard-library/56426/37 "2022-04-07T03:48:17Z")

</div>

Yes, if this proves to be important, I think it may still be possible to add `Clock.Duration` via a small amendment to SE-0329. Cc @Philippe_Hausler @John_McCall

---

<div class="post-metadata">

**Author:** ![stephencelis](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/stephencelis/32/2675_2.png) [@stephencelis](https://forums.swift.org/u/stephencelis)\
**Post date:** [April 7, 2022, 3:50am UTC](https://forums.swift.org/t/pitch-primary-associated-types-in-the-standard-library/56426/38 "2022-04-07T03:50:41Z")

</div>

I'd be happy to provide some concrete examples to further motivate an amendment, if my earlier point wasn't clear. Just let me know!

---

<div class="post-metadata">

**Author:** ![John\_McCall](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/john_mccall/32/1351_2.png) [@John\_McCall](https://forums.swift.org/u/John_McCall)\
**Post date:** [April 7, 2022, 3:59am UTC](https://forums.swift.org/t/pitch-primary-associated-types-in-the-standard-library/56426/39 "2022-04-07T03:59:27Z")

</div>

I don't have a problem with allowing this adjustment if Philippe thinks it's a good idea; I wouldn't say it needs evolution approval.

An alternative approach would be to allow primary associated types to be paths, e.g. `protocol Clock<Instant.Duration> { ... }`, but that might not be a good idea, and it probably _would_ need evolution approval.

---

<div class="post-metadata">

**Author:** ![lorentey](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/lorentey/32/1299_2.png) [@lorentey](https://forums.swift.org/u/lorentey)\
**Post date:** [April 11, 2022, 10:32pm UTC](https://forums.swift.org/t/pitch-primary-associated-types-in-the-standard-library/56426/40 "2022-04-11T22:32:41Z")

</div>

I submitted these PRs to introduce `Duration` as an associated type requirement of `Clock`:

[swift-evolution#1618](https://github.com/apple/swift-evolution/pull/1618) - Amend SE-0329 to add `Clock.Duration`  
[swift/main#42314](https://github.com/apple/swift/pull/42314) - [stdlib] Add `Clock.Duration` as an associated type requirement  
[swift/release/5.7#42316](https://github.com/apple/swift/pull/42316) - [5.7][stdlib] Add `Clock.Duration` as an associated type requirement

---

<div class="post-metadata">

**Author:** ![John\_McCall](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/john_mccall/32/1351_2.png) [@John\_McCall](https://forums.swift.org/u/John_McCall)\
**Post date:** [April 12, 2022, 9:25pm UTC](https://forums.swift.org/t/pitch-primary-associated-types-in-the-standard-library/56426/41 "2022-04-12T21:25:55Z")

</div>

The Core Team agreed that this is an acceptable change to make retroactively without further review. Let's do it.

[Previous page](https://forums.swift.org/t/pitch-primary-associated-types-in-the-standard-library/56426.md?page=1)

[Next page](https://forums.swift.org/t/pitch-primary-associated-types-in-the-standard-library/56426.md?page=3)
