Suppose I have a protocol that represents a relationship between two instances, one of type Alphabet and the other of type Symbol:
protocol TableProtocol {
associatedtype Alphabet
associatedtype Symbol
subscript(_ of: Alphabet) -> Int? { get }
subscript(_ of: Symbol) -> Int? { get }
}
However, it's possible for Alphabet and Symbol to be the same type, in which case subscript(_ of: Symbol) -> Int? { get } is the same functionality provided by subscript(_ of: Alphabet) -> Int? { get }.
I can write an implementation that specifies only subscript(_ of: Alphabet) -> Value? { get } and this compiles (both functions in the protocol are satisfied by this concrete function):
struct CharacterTable: TableProtocol {
typealias Alphabet = Character
typealias Symbol = Character
subscript(_ of: Character) -> Int? { /* ... */ }
}
The compiler understands that this single subscript implements both requirements in the protocol.
I think this reveals a flaw in the design, if you want to use it in that way. Formally, an alphabet would be a set of symbols, even if the cardinality of that set is one. Is there a reason you can't represent the simplified/generic version in that way instead of trying to overlap the two concepts?
This is mostly an example, but it does hint at the project I'm working on: A variation of finite state machine where the alphabet may be of infinite cardinality, so long as there's still a finite number of states with a finite number of transitions; however a transition is allowed to occur over a set of values (possibly infinite size), for example, a transition over the floating point numbers 0..<1. In this case, the value type of the transition table may mismatch the value type of an individual symbol.
I considered this, but it doesn't make much sense on its face. The ranges of values that are associated with a single transition are opaque and can usually be treated as an atomic value. Or you're dealing with symbols in a string. This struct is the only place these two data types meet.
Can you do this? I looked through the documentation but I didn't see this as an option.
"Argument labels" are the first ones, which you're currently ignoring via _. "Parameter names" are the ones where you're using "of". It doesn't make sense to use "of" as a parameter name, because "of" is the preposition, not the object of the preposition, which a parameter name can be.
I'm not convinced there's not a better solution to your problem, but I can't comprehend it without a concrete example or too much thinking time.
This is... interesting, I didn't realize there was a "default label" behavior, or that it was different for subscripts; this doesn't seem to be documented anywhere.
The names I gave are just arbitrary examples, this isn't an underlying problem. Inside the automata, the values need only be Equatable and Hashable, there's no other meaning to their value. And how would you even specify a condition like Element != Self?
I think the problem I'm facing is as I described, that I ought to be able to add conditions like that two functions be equal when two types are equal. Adding labels to subscripts is a satisfactory workaround, it's just not aesthetic.
Aside, I think the flaw with SetAlgebra is that it combines element membership, mutation, and set algebra all within the same protocol, and two of these three things don't necessarily make sense for bit collections, these should be three separate protocols. It's the assumption that all sets are completely enumerable and any arbitrary value can be tested for membership in any set that is the root of evil like Russell's paradox.