protocol Mappable {
  associatedtype Context<T> // this is the only impossible line

  static func map<A, B>(_ fa: Context<A>, _ f: (A) -> B) -> Context<B>
}

extension Array: Mappable {
  typealias Context<T> = Array<T>

  static func map<A, B>(_ fa: Array<A>, _ f: (A) -> B) -> Array<B> {
    fa.map(f)
  }
}

extension Optional: Mappable {
  typealias Context<T> = Optional<T>

  static func map<A, B>(_ fa: Optional<A>, _ f: (A) -> B) -> Optional<B> {
    fa.map(f)
  }
}

extension Task: Mappable where Failure == Error {
  typealias Context<T> = Task<T, Error>

  static func map<A, B>(_ fa: Task<A, Error>, _ f: @escaping (A) -> B) -> Task<B, Error> {
    Task {
      let a = await fa.value
      return f(a)
    }
  }
}

extension Result: Mappable where Failure == Error {
  typealias Context<T> = Result<T, Error>

  static func map<A, B>(_ fa: Result<A, Error>, _ f: (A) -> B) -> Result<B, Error> {
    fa.map(f)
  }
}