Extract Payload for enum cases having associated value

I did this with a playground:

Given an enum

public struct Person {
    var name: String
    var lastName: String
}

public enum Foo {
    case bar(Person)
}

Let's define the class CasePattern. Please ignore current implementation. It was needed to make it compile.

public class CasePattern<Root, Value> {
    public enum PatternError: Error {
        case patternMismatch(String)
    }
    
    internal var get: (Root) throws -> Value
    
    internal init(get: @escaping (Root) throws -> Value) {
        self.get = get
    }
    
    func appending<AppendedValue>(path: KeyPath<Value, AppendedValue>) -> CasePattern<Root, AppendedValue> {
        return CasePattern<Root, AppendedValue> { root throws -> AppendedValue in
            (try self.get(root))[keyPath: path]
        }
    }
}

Now we extend the enum to expose CasePatterns. Again, ignore the implementation. It was needed just to make it compile.

public extension CasePattern where Root == Foo {
    static var bar: CasePattern<Root, Person> {
        CasePattern<Root, Person> {
            guard case let .bar(value) = $0 else {
                throw PatternError.patternMismatch("\($0) does not match pattern .bar")
            }
            return value
        }
    }
}

Now this is possible:

extension Foo {
/// Not possible until https://github.com/apple/swift/pull/22749
//    subscript<Value>(case pattern: CasePattern<Self, Value>)throws -> Value {
//        try pattern.get(self)
//    }

    // Just to make it compile
    subscript<Value>(case pattern: CasePattern<Self, Value>) -> () throws -> Value {
        { try pattern.get(self) }
    }
}

let e = Foo.bar(Person(name: "David", lastName: "Bowie"))


let kp: KeyPath<Person, String> = \.name // regular keyPath for Person to name property
let cp: CasePattern<Foo, Person> = .bar // with the help of the compiler should be \.bar

let cpKp = cp.appending(path: kp) // With the help of the compiler should be \Foo.bar.name
try e[case: cpKp]() // prints "David"

CasePattern and KeyPath can be combined.