Skip to content

Instantly share code, notes, and snippets.

@atierian
Last active January 25, 2023 17:47
Show Gist options
  • Save atierian/bd46b3f20799259c112f3bafc29ddf60 to your computer and use it in GitHub Desktop.
Save atierian/bd46b3f20799259c112f3bafc29ddf60 to your computer and use it in GitHub Desktop.
(ab)using enum pattern matching to lift generic types to specific types and vice-versa in a type-safe way
// MARK: Interface Module
struct Request<Output> {
let kind: Kind
enum Kind {
case one((Int) -> Output)
case two((String) -> Output)
}
}
extension Request where Output == Int {
static func exampleOne() -> Self {
.init(kind: .one({ $0 }))
}
}
extension Request where Output == String {
static func exampleTwo() -> Self {
.init(kind: .two({ $0 }))
}
}
protocol Thing {
func doThing<Output>(
_ request: Request<Output>
) -> Output
}
// MARK: Implementation Module
struct Concrete: Thing {
func doThing<Output>(
_ request: Request<Output>
) -> Output {
switch request.kind {
case .one(let lift):
return lift(42)
case .two(let lift):
return lift("hello, world!")
}
}
}
// MARK: Callsite
let thing: Thing = Concrete()
thing.doThing(.exampleOne())
thing.doThing(.exampleTwo())
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment