Created
October 24, 2021 18:58
-
-
Save oliverfoggin/697e9340a5705800adf6ec5ae4cac29d to your computer and use it in GitHub Desktop.
Trying to recreate the behaviour of Optional...
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
enum Foo<Wrapped> { | |
case no | |
case yes(Wrapped) | |
} | |
extension Foo: ExpressibleByNilLiteral { | |
init(nilLiteral: ()) { | |
self = .no | |
} | |
} | |
extension Foo { | |
init(_ value: Wrapped) { | |
self = .yes(value) | |
} | |
} | |
extension Foo: Equatable where Wrapped: Equatable { | |
static func ==(lhs: Foo<Wrapped>, rhs: Foo<Wrapped>) -> Bool { | |
switch (lhs, rhs) { | |
case let (.yes(l), .yes(r)): | |
return l == r | |
case (nil, nil): | |
return true | |
default: | |
return false | |
} | |
} | |
} | |
@frozen | |
public struct _OptionalNilComparisonType: ExpressibleByNilLiteral { | |
/// Create an instance initialized with `nil`. | |
@_transparent | |
public init(nilLiteral: ()) { | |
} | |
} | |
extension Foo { | |
public static func ~=(lhs: _OptionalNilComparisonType, rhs: Foo<Wrapped>) -> Bool { | |
switch rhs { | |
case .yes: | |
return false | |
case .no: | |
return true | |
} | |
} | |
public static func ==(lhs: Foo<Wrapped>, rhs: _OptionalNilComparisonType) -> Bool { | |
switch lhs { | |
case .yes: | |
return false | |
case .no: | |
return true | |
} | |
} | |
public static func !=(lhs: Foo<Wrapped>, rhs: _OptionalNilComparisonType) -> Bool { | |
switch lhs { | |
case .yes: | |
return true | |
case .no: | |
return false | |
} | |
} | |
public static func ==(lhs: _OptionalNilComparisonType, rhs: Foo<Wrapped>) -> Bool { | |
switch rhs { | |
case .yes: | |
return false | |
case .no: | |
return true | |
} | |
} | |
public static func !=(lhs: _OptionalNilComparisonType, rhs: Foo<Wrapped>) -> Bool { | |
switch rhs { | |
case .yes: | |
return true | |
case .no: | |
return false | |
} | |
} | |
} | |
extension Foo: Hashable where Wrapped: Hashable { | |
/// Hashes the essential components of this value by feeding them into the | |
/// given hasher. | |
/// | |
/// - Parameter hasher: The hasher to use when combining the components | |
/// of this instance. | |
@inlinable | |
func hash(into hasher: inout Hasher) { | |
switch self { | |
case .no: | |
hasher.combine(0 as UInt8) | |
case .yes(let wrapped): | |
hasher.combine(1 as UInt8) | |
hasher.combine(wrapped) | |
} | |
} | |
} | |
func ~=<Wrapped>(pattern: Wrapped, value: Foo<Wrapped>) -> Bool where Wrapped: Equatable { | |
return Foo.yes(pattern) == value | |
} | |
enum Bar { | |
case a | |
} | |
//let f: Foo<Bar> = .yes(.a) | |
let f: Foo<Bar> = nil | |
switch f { | |
case nil: | |
print("Nothing to see here") | |
case .a: | |
print("A") | |
case .no: | |
print("No") | |
case .yes(let value): | |
print(value) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
@isaac-weisberg not really. You can only get so far. Optional has special privileges built into the compiler that allow it to get around stuff that just isn’t possible for use defined types.
like, you still need to provide .no in the switch even though nil covers that. Etc…
also, the fact that Optional is @Frozen means they don’t have to worry about adding new cases etc…