Skip to content

Instantly share code, notes, and snippets.

@tarunon
Created July 22, 2020 05:57
Show Gist options
  • Save tarunon/9b18557123e6c5a793810f69e76de566 to your computer and use it in GitHub Desktop.
Save tarunon/9b18557123e6c5a793810f69e76de566 to your computer and use it in GitHub Desktop.
Traits flatMap with FB
struct Single<T> {}
struct Maybe<T> {}
protocol MaybeCov {
associatedtype T
func asMaybe() -> Maybe<T>
}
extension Single: MaybeCov {
func asMaybe() -> Maybe<T> { fatalError() }
}
extension Maybe: MaybeCov {
func asMaybe() -> Maybe<T> { fatalError() }
}
@_functionBuilder
struct Builder {
enum Either<First, Second> {
case first(First)
case second(Second)
}
public static func buildBlock() -> Void {
}
public static func buildBlock<C>(_ c: C) -> C {
c
}
public static func buildEither<T, F>(first: T) -> Either<T, F> {
.first(first)
}
public static func buildEither<T, F>(second: F) -> Either<T, F> {
.second(second)
}
}
extension Builder.Either: MaybeCov where First: MaybeCov, Second: MaybeCov, First.T == Second.T {
func asMaybe() -> Maybe<First.T> {
switch self {
case .first(let first): return first.asMaybe()
case .second(let second): return second.asMaybe()
}
}
}
extension Single {
func flatMap<M: MaybeCov>(@Builder _ f: (T) -> M) -> Maybe<M.T> {
f(fatalError() as! T).asMaybe()
}
}
let res = Single<Int>().flatMap { (arg) in
if arg % 2 == 0 {
Single<String>()
} else {
Maybe<String>()
}
}
// res is Maybe<String>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment