Skip to content

Instantly share code, notes, and snippets.

@LemonSpike
Last active March 5, 2021 02:53
Show Gist options
  • Save LemonSpike/acf42b554eca12eddb5f2ad4a34ff207 to your computer and use it in GitHub Desktop.
Save LemonSpike/acf42b554eca12eddb5f2ad4a34ff207 to your computer and use it in GitHub Desktop.
Recursive Swift Either Enum with Associated Values
enum RecursiveEither<Left, Right> {
case left(ValueOrRecursiveEither<Left, Left, Right>)
case right(ValueOrRecursiveEither<Right, Left, Right>)
var left: Left? {
switch self {
case .left(.value(let left)):
return left
case .left(.either(let left)):
return left.left
case .right:
return nil
}
}
var right: Right? {
switch self {
case .left:
return nil
case .right(.either(let right)):
return right.right
case .right(.value(let right))::
return right
}
}
}
enum ValueOrRecursiveEither<Value, Left, Right> {
case value(Value)
indirect case either(RecursiveEither<Left, Right>)
}
let e = RecursiveEither<Int, Int>.left(.value(4))
let f = RecursiveEither<Int, Int>.left(.either(.left(.value(5))))
let g = RecursiveEither<Int, Int>.left(.either(.right(.value(8))))
let h = RecursiveEither<Int, Int>.right(.value(7))
print(e.left) // prints Optional(4)
print(f.left) // prints Optional(5)
print(g.left) // prints nil
print(h.left) // prints nil
let e = RecursiveEither2<Int, Int>.left(.left(.left(.left(.value(3)))))
let eTwo = RecursiveEither2<Int, Int>.right(.right(.right(.right(.value(3)))))
enum RecursiveEither2<Left, Right> {
case left(ValueOrLeftOrRight<Left, Left, Right>)
case right(ValueOrLeftOrRight<Right, Left, Right>)
var left: Left? {
guard case .left(let content) = self else { return nil }
return content.left
}
var right: Right? {
guard case .right(let content) = self else { return nil }
return content.right
}
}
enum ValueOrLeftOrRight<Value, Left, Right> {
case value(Value)
indirect case left(ValueOrLeftOrRight<Left, Left, Right>)
indirect case right(ValueOrLeftOrRight<Right, Left, Right>)
var left: Left? {
switch self {
case .value(let left): return left as? Left
case .left(let left): return left.left
default: return nil
}
}
var right: Right? {
switch self {
case .value(let right): return right as? Right
case .right(let right): return right.right
default: return nil
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment