Skip to content

Instantly share code, notes, and snippets.

@prachigauriar
Last active August 18, 2017 03:21
Show Gist options
  • Save prachigauriar/ebc27db5c7ca21a89eeb25efc21c3b80 to your computer and use it in GitHub Desktop.
Save prachigauriar/ebc27db5c7ca21a89eeb25efc21c3b80 to your computer and use it in GitHub Desktop.
import Foundation
public enum Result<Value> {
case success(Value)
case failure(Error)
}
// Parent Protocol
public protocol Handler {
associatedtype Input
associatedtype Output
func handle(_ result: Result<Input>, completion: @escaping (Result<Output>) -> Void)
}
// Child Protocol
// The goal here is that many types can implement this much simpler method and get Handler
// conformance for free.
public protocol Transformer : Handler {
func transform(_ input: Input) throws -> Output
}
public extension Transformer {
public func handle(_ result: Result<Input>, completion: @escaping (Result<Output>) -> Void) {
switch result {
case let .success(input):
do {
completion(.success(try transform(input)))
} catch {
completion(.failure(error))
}
case let .failure(error):
completion(.failure(error))
}
}
}
// Conforming struct. I get many errors with most conforming types unless I explicitly create typealiases for
// Input and Output.
// Errors:
// error: ChildProtocolsWithAssociatedTypes.playground:39:15: error: type 'TransformerBlock<BlockInput, BlockOutput>' does not conform to protocol 'Transformer'
// public struct TransformerBlock<BlockInput, BlockOutput> : Transformer {
// ^
//
// ChildProtocolsWithAssociatedTypes.playground:48:17: note: candidate has non-matching type '<BlockInput, BlockOutput> (BlockInput) throws -> BlockOutput'
// public func transform(_ input: BlockInput) throws -> BlockOutput {
// ^
//
// error: ChildProtocolsWithAssociatedTypes.playground:39:15: error: type 'TransformerBlock<BlockInput, BlockOutput>' does not conform to protocol 'Handler'
// public struct TransformerBlock<BlockInput, BlockOutput> : Transformer {
// ^
//
// ChildProtocolsWithAssociatedTypes.playground:18:10: note: protocol requires function 'transform' with type '(<<error type>>) throws -> <<error type>>'; do you want to add a stub?
// func transform(_ input: Input) throws -> Output
// ^
//
// ChildProtocolsWithAssociatedTypes.playground:7:20: note: protocol requires nested type 'Input'; do you want to add it?
// associatedtype Input
// ^
//
// ChildProtocolsWithAssociatedTypes.playground:8:20: note: protocol requires nested type 'Output'; do you want to add it?
// associatedtype Output
// ^
public struct TransformerBlock<BlockInput, BlockOutput> : Transformer {
// public typealias Input = BlockInput
// public typealias Output = BlockOutput
public let block: (BlockInput) throws -> BlockOutput
public init(block: @escaping (BlockInput) throws -> BlockOutput) {
self.block = block
}
public func transform(_ input: BlockInput) throws -> BlockOutput {
return try block(input)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment