Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- // NOTE: This is an experiement that does not actually work (in the 2/8/18 nightly toolchain).
- // The idea is to use Swift's constraint inference to be able to abstract an arbitrary set of constraints.
- /// An empty enum serving as an example of the general case of
- /// representing a set of constraints that relate multiple types.
- /// This specific example provides the constraint that both types are sequences and they have the same Element type.
- enum Parallel<S1: Sequence, S2: Sequence> where S1.Element == S2.Element {
- typealias First = S1
- typealias Second = S2
- }
- /// A function that uses a phantom argument intended to get the compiler to infer the constraints
- /// represented by the Parallel.
- /// This seems to work but can produce extremely unhelpful error messages, far worse than the error messages
- /// that would be produced if the constraints were stated explicitly here. It is also rather verbose at the usage site.
- func foo<S1, S2>(_ s1: S1, _ s2: S2, constriants: Parallel<S1, S2>.Type = Parallel<S1, S2>.self) {
- print(s1)
- print(s2)
- }
- // compiler allows this as expected
- foo([1, 2], [1, 2] as Set)
- // Compiler rejects this with a useful error message:
- // - candidate requires that the types 'Int' and 'String' be equivalent (requirement specified as 'S1.Element' == 'S2.Element' [with S1 = [Int], S2 = Set<String>])
- // foo([1, 2], ["1", "2"] as Set)
- // Compiler rejects this but with a non-obvious error message:
- // - cannot invoke 'foo' with an argument list of type '(Int, Int)'
- // - note: expected an argument list of type '(S1, S2, constriants: Parallel<S1, S2>.Type)'
- // foo(42, 43)
- // Given the prior two examples it appears that the compiler infers the constraints on S1 and S2
- // as desired when the types both have Sequence conformances despite not meeting other constraints
- // specified by Parallel, but only omits the default argument when they do not have the conformances.
- /// A function that uses a where clause intended to get the compiler to infer the constraints
- /// represented by the Parallel. Ideally this could simply be stated as Parallel<S1, S2>.
- func bar<S1, S2>(_ s1: S1, _ s2: S2) where S1 == Parallel<S1, S2>.First {
- print(s1)
- print(s2)
- }
- foo([1, 2], [1, 2] as Set)
- // Compiler unfortunately allows this.
- bar([1, 2], ["1", "2"] as Set)
- // Compiler does not allow this but fails with the same unhelpful diagnostic as in foo(42, 43)
- //foo(42, 43)
- /// A type that uses a where clause intended to get the compiler to infer the constraints
- /// represented by the Parallel. Ideally this could simply be stated as Parallel<S1, S2>.
- struct Pair<S1, S2> where S1 == Parallel<S1, S2>.First {
- let first: S1
- let second: S2
- }
- print(Pair(first: [1, 2], second: [1, 2] as Set))
- // As with bar, the compiler unfortunately allows this
- print(Pair(first: [1, 2], second: ["1", "2"] as Set))
- // Again, unfortunately the compiler allows this
- print(Pair(first: 42, second: 43))
Add Comment
Please, Sign In to add comment