Swift Conditional Conformance with Any

Swift Conditional Conformance with Any

You can create a generic method and remove the constraint from the extension:

extension Sequence {
func reduced<T>() -> Result<[T], Error> where Element == Result<T, Error> {
reduce(.success([])) {
switch $0 {
case .failure: return $0
case let .success(array):
switch $1 {
case let .failure(error): return .failure(error)
case let .success(value): return .success(array + CollectionOfOne(value))
}
}
}
}
}

Btw you can also use a plain loop and provide an early exit at the first failure:

extension Sequence {
func reduced<T>() -> Result<[T], Error> where Element == Result<T, Error> {
var array: [T] = []
for result in self {
switch result {
case let .failure(error): return .failure(error)
case let .success(value): array.append(value)
}
}
return .success(array)
}
}

A more concise approach would be to create a generic method that throws or return an array with all successes:

extension Sequence {
func successes<T, E>() throws -> [T] where Element == Result<T, E>, E: Error {
try map { try $0.get() }
}
}

Playground testing:

let z: [Result<Int, MyError>] = [.success(1),
.success(2),
.success(3)] //,
//.failure(.blah)]
do {
let successes = try z.successes()
print(successes) // [1, 2, 3]
} catch {
print(error)
}

Conditional Protocol Conformance to Protocol

The reason why this is not allowed is stated here:

This protocol extension would make any Collection of Equatable elements Equatable, which is a powerful feature that could be put to good use. Introducing conditional conformances for protocol extensions would exacerbate the problem of overlapping conformances, because it would be unreasonable to say that the existence of the above protocol extension means that no type that conforms to Collection could declare its own conformance to Equatable, conditional or otherwise.

See also this question.

If you just don't want to write the duplicate implementation of intRepr everytime, you can do this:

struct StringContainer : ShowableAsIntContainer {
typealias T = String
let element: String
}

struct IntContainer : ShowableAsIntContainer {
typealias T = Int
let element: Int
}

extension Container where T : ShowableAsInt {
func intRepr() -> Int {
return element.intRepr()
}
}

typealias ShowableAsIntContainer = ShowableAsInt & Container

Why 'there cannot be more than one conformance, even with different conditional bounds'?

Is it impossible? Yes and no. It's not currently possible in Swift, as it has been implemented. It is in principle possible to be implemented.

The name for this is "overlapping conformances", and it was explicitly and purposely rejected. You can find the rationale in the "Alternatives considered" section of SE-0143 Conditional conformances. The TL;DR is: because it's really complicated.

Without knowing more about what exactly you were trying to use this for, there's not much direction we can provide.

Conditional Conformance: Using 'T' as a concrete type conformance to 'T' is not supported

Change the extension to Element is rather than Element conforms to

extension Array where Element == Social {
func speak() {
forEach { $0.speak() }
}
}

The constraint Array : Social is irrelevant.

Conditional protocol conformance?

This was implemented in Swift 4.1.

Conditional Protocol Conformance: Cannot convert value of type 'Array_' to specified type '[UInt8]'

In order for Array<UInt8> to be BinaryCodable, its element type UInt8 must be BinaryCodable, which it isn't. That protocol has
default implementations of its required methods, but conformance must
still be declared explicitly:

extension UInt8: BinaryCodable {}

Then your extension String compiles,
and you can even get rid of the forced cast as! BinaryCodable in the
encoding method (and using guard allows to save one line):

extension String: BinaryCodable {
public func binaryEncode(to encoder: BinaryEncoder) throws {
try Array(self.utf8).binaryEncode(to: encoder)
}

public init(fromBinary decoder: BinaryDecoder) throws {
let utf8: [UInt8] = try Array(fromBinary: decoder)
guard let str = String(bytes: utf8, encoding: .utf8) else {
throw BinaryDecoder.Error.invalidUTF8(utf8)
}
self = str
}
}

How can I get conditional protocol conformance with a protocol's parent?

The question as posed, "How can I get conditional protocol conformance with a protocol's parent?" is meaningless, because a protocol always conforms with its parent; there is no "conditional" about it.

As for your actual code, the problem is the phrase A<Resource>. Saying A<Resource> is not a correct resolution of A's T. You need to resolve T as a class, struct, or enum — not as a protocol.

For example, if you have a class B that conforms to Resource, you can declare

let a = A<B>()

and all is well.

if there was a way to let A<Resource> know that it will always be working with concrete types that conform to Codable

Well, as I said, your code compiles fine as soon as A is working with a concrete type that does conform to Codable. So if that's what A will always be working with, there's nothing more to do. You could of course tell A that its T will always conform to Resource (which by definition will always conform to Codable):

class A<T:Resource> {}

Swift Conditional conformances with Generic Type

A constraint on the extension can restrict the placeholder type E to concrete types or protocols, for example:

extension Box where E: Item<Any> {}
extension Box where E == String {}
extension Box where E: Numeric {}

But you cannot put a generic constraint on the extension:

extension Box<A> where E: Item<A> {}
// Error: Constrained extension must be declared on the unspecialized generic
// type 'Box' with constraints specified by a 'where' clause

The solution is to restrict the method instead:

extension Box  {
func mapOnItem<A, B>(function: (A) -> B) -> Box<Item<B>> where E: Item<A> {
return Box<Item<B>>(val: Item(val: function(self.value.value)))
}
}

Workaround for conditional conformance in Swift (was: Adding protocol to a constrained generic types)

An updated answer now that we have Swift 4.2, conditional conformance is now added as a feature.

From their spec on Github, this sort of code is now valid

   extension List : Printable where T: SomeType {
func className() -> String {
return "List<SomeType>"
}
}


Related Topics



Leave a reply



Submit