Skip to content

Instantly share code, notes, and snippets.

@pcantrell
Created August 7, 2016 16:57
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save pcantrell/097cb7c08f9da4650c74a702d5f80450 to your computer and use it in GitHub Desktop.
Save pcantrell/097cb7c08f9da4650c74a702d5f80450 to your computer and use it in GitHub Desktop.
Swift type erasure type puzzler
import Foundation
// ——— The Setup ———
protocol Foo
{
associatedtype Bar
func modify(bar: Bar) -> Bar
}
struct Greeter: Foo
{
func modify(bar: String) -> String
{ return "Hi, \(bar)" }
}
struct Multiplier: Foo
{
var factor: Int
func modify(bar: Int) -> Int
{ return bar * factor }
}
struct FooBarPair<F, B where F: Foo, B == F.Bar>
{
var foo: F
var bar: B
func apply()
{ print(foo.modify(bar)) }
}
let a = FooBarPair(foo: Greeter(), bar: "ih")
let b = FooBarPair(foo: Multiplier(factor: 6), bar: 7)
// ——— The Puzzle ———
// Suppose I have an array of [a,b], and I want to call apply() on every element.
//
// Note that a caller doesn’t need to know the generic types F, B to call apply().
// If Swift allowed the existential type [FooBarPair], then this would be easy!
// But Swift doesn’t, and it isn’t.
//
// The approach below is the best I’ve found. Is there a simplier way?
protocol AnnoyingTypeErasingProtocol
{
func apply()
}
extension FooBarPair: AnnoyingTypeErasingProtocol { }
let pairs: [AnnoyingTypeErasingProtocol] = [a,b]
for pair in pairs
{ pair.apply() }
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment