Forked from andymatuschak/gist:a40c4c699c0abdd704ce
Created
January 27, 2018 01:54
-
-
Save jakebromberg/313cd471147c740437ad9e8d65f68c8c to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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 Smashable { | |
func smash(with value: HeteroEquatable) -> HeteroEquatable | |
} | |
extension Int: HeteroEquatable { } | |
extension HeteroEquatable where Self: Equatable { | |
func isEqualTo(_ value: HeteroEquatable) -> Bool { | |
guard let value = value as? Self else { | |
return false | |
} | |
return self == value | |
} | |
} | |
struct Test: Smashable { | |
func smash(with value: HeteroEquatable) -> HeteroEquatable { | |
return 3 // This is free to return a different adopter of Value | |
} | |
} | |
let result = Test().smash(with: 3) | |
print(result == 3) // can still == |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Why is the indirection of the
Value
protocol necessary?