 /// An `AnyArrayBuffer` dispatcher that provides algorithm implementations for `Factor`
 /// elements.
 class FactorArrayDispatch {
+  /// The notional `Self` type of the methods in the dispatch table
+  typealias Self_ = AnyArrayBuffer<AnyObject>
+  
   /// A function returning the errors, at `x`, of the factors in `storage`.
   ///
   /// - Requires: `storage` is the address of an `ArrayStorage` whose `Element` has a
   ///   subclass-specific `VectorFactor` type.
-  final let errors: (_ storage: UnsafeRawPointer, _ x: VariableAssignments) -> [Double]
+  final let errors: (_ self_: Self_, _ x: VariableAssignments) -> [Double]
 
   /// Creates an instance for elements of type `Element`.
-  init<Element: Factor>(_: Type<Element>) {
-    let storageType = Type<ArrayStorage<Element>>()
-    errors = { storage, x in storage[as: storageType].errors(at: x) }
+  init<Element: Factor>(_ e: Type<Element>) {
+    errors = {
+      self_, x in self_[unsafelyAssumingElementType: e].storage.errors(at: x)
+    }
   }
 }
 

extension AnyArrayBuffer where Dispatch: VectorFactorArrayDispatch {
  /// Returns the error vectors, at `x`, of the factors.
  func errorVectors(at x: VariableAssignments) -> AnyVectorArrayBuffer {
    withUnsafePointer(to: storage) { dispatch.errorVectors($0, x) }
  }

  /// Returns the linearizations, at `x`, of the factors.
  func linearized(at x: VariableAssignments) -> AnyGaussianFactorArrayBuffer {
    withUnsafePointer(to: storage) { dispatch.linearized($0, x) }
  }
}


  /// - Requires: `storage` is the address of an `ArrayStorage` whose `Element` has a
  ///   subclass-specific `VectorFactor` type.
  final let errorVectors:
    (_ self_: Self_, _ x: VariableAssignments) -> AnyVectorArrayBuffer

  /// A function returning the linearizations, at `x`, of the factors in `storage`.
  ///
  /// - Requires: `storage` is the address of an `ArrayStorage` whose `Element` has a
  ///   subclass-specific `VectorFactor` type.
  final let linearized:
    (_ self_: Self_, _ x: VariableAssignments) -> AnyGaussianFactorArrayBuffer

  /// Creates an instance for elements of type `Element` using the given `Linearization`.
  init<Element: VectorFactor, Linearization: LinearApproximationFactor>(
    _ e: Type<Element>, linearization: Type<Linearization>
  )
    where Linearization.Variables == Element.LinearizableComponent.Variables.TangentVector,
          Linearization.ErrorVector == Element.ErrorVector
  {
    errorVectors = { self_, x in
      .init(self_[unsafelyAssumingElementType: e].storage.errorVectors(at: x))
    }
    
    linearized = { self_, x in
      .init(
        self_[unsafelyAssumingElementType: e].storage.linearized(at: x)
          as ArrayBuffer<Linearization>
      )
    }
    super.init(e)
  }
}

