 
 /// A van Laarhoven Lens type
 public protocol LensType {
-    associatedtype A
-    associatedtype B
-
-    func set(_ target: inout A, _ value: B)
-    func get(_ target: A) -> B
+    associatedtype Root
+    associatedtype Value
+
+    func set(_ target: inout Root, _ value: Value)
+    func get(_ target: Root) -> Value
 }
 
 public extension LensType {
     /// Converts this lens to an optional prism that allows lossy getting/setting of optional values
     ///
     /// - See Also: `ChannelType.prism`
-    @inlinable var prism : Lens<A?, B?> {
-        return Lens<A?, B?>(get: { $0.flatMap(self.get) }, set: { (whole, part) in
+    @inlinable var prism : Lens<Root?, Value?> {
+        return Lens<Root?, Value?>(get: { $0.flatMap(self.get) }, set: { (whole, part) in
             if var wholeActual = whole, let part = part {
                 self.set(&wholeActual, part)
                 whole = wholeActual

/// conditional creation for complex immutable state structures.
///
/// See Also: https://github.com/apple/swift/blob/master/docs/GenericsManifesto.md#higher-kinded-types
public struct Lens<A, B> : LensType {
    @usableFromInline let getter: (A) -> B
    @usableFromInline let setter: (inout A, B) -> ()

    @inlinable public init(get: @escaping (A) -> B, set: @escaping (inout A, B) -> ()) {
        self.getter = get
        self.setter = set
    }

    @inlinable public init(kp: WritableKeyPath<A, B>) {
        self.getter = { $0[keyPath: kp] }
        self.setter = { $0[keyPath: kp] = $1 }
    }

    @inlinable public func set(_ target: inout A, _ value: B) {
        return setter(&target, value)
    }

    @inlinable public func get(_ target: A) -> B {
        return getter(target)
    }
}

/// A `WritableKeyPath` is fundamentally a `Lens`


    @inlinable public func set(_ target: inout Root, _ value: Value) {
        target[keyPath: self] = value
    }
}

public extension Lens {
    /// Constructs a `Lens` from a `WritableKeyPath`
    @inlinable init(kp: WritableKeyPath<Root, Value>) {
        self.getter = { $0[keyPath: kp] }
        self.setter = { $0[keyPath: kp] = $1 }
    }
}

