Skip to content

Instantly share code, notes, and snippets.

@andymatuschak
Last active February 3, 2018 22:55
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save andymatuschak/a40c4c699c0abdd704ce to your computer and use it in GitHub Desktop.
Save andymatuschak/a40c4c699c0abdd704ce to your computer and use it in GitHub Desktop.
// One note before we start: if the inhabitants of Value are a closed set,
// then making Value an enum is going to be a clearer model than using a
// protocol like this. I'm assuming you need to be able to retroactively add
// new members of Value.
// Can't use Equatable directly because of its Self requirement.
protocol HeteroEquatable {
func isEqualTo(value: HeteroEquatable) -> Bool
}
func ==(lhs: HeteroEquatable, rhs: HeteroEquatable) -> Bool {
return lhs.isEqualTo(rhs)
}
protocol Value: HeteroEquatable {}
protocol Smashable {
func valueBySmashingOtherValue(value: Value) -> Value
}
extension Int: Value {
func isEqualTo(a: HeteroEquatable) -> Bool {
if let a = a as? Int {
return self == a
} else {
return false
}
}
}
struct Test {
func valueBySmashingOtherValue(value: Value) -> Value {
return 0 // This is free to return a different adopter of Value
}
}
let result = Test().valueBySmashingOtherValue(3)
println(result == 3) // can still ==
@andymatuschak
Copy link
Author

Okay. No. I don't think it's fixable in Swift currently.

Per @jckarter, Value can't be both Equatable and used as a dynamic type because Equatable requires a Self constraint, but the result of valueBySmashingOtherValue would be type-erased, so you couldn't actually use it as an equatable…

You could get around this by making Value heterogeneously equatable.

@andymatuschak
Copy link
Author

(updated to a version with Value heterogeneously equatable)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment