title: How to create a purely functional ad-hoc polymorphic lens without any introspection?
body: <p>I adapted DrBoolean's <a href="https://github.com/DrBoolean/lenses/blob/master/src/lenses.js" rel="nofollow noreferrer">lens implementation</a>, so that it works without introspection/duck typing/relying on prototype identities. The computation should be exclusively determined by continuations and function arguments of higher order functions. I've come this far:</p>
  
  <p><div class="snippet" data-lang="js" data-hide="false" data-console="true" data-babel="false">
  <div class="snippet-code">
  <pre class="snippet-code-js lang-js prettyprint-override"><code>const id = x =&gt; x;
  
  // compose n functions (right to left)
  const $$ = (f, ...fs) =&gt; x =&gt;
    fs.length === 0
      ? f(x)
      : f($$(...fs) (x));
  
  // function encoded Const type
  const Const = x =&gt; k =&gt; k(x);
  const constMap = f =&gt; fx =&gt; fx(x =&gt; Const(x));
  const runConst = fx =&gt; fx(id);
  
  // lens constructor
  const objLens = k =&gt; cons =&gt; o =&gt;
    constMap(v =&gt; Object.assign({}, o, {[k]: v})) (cons(o[k]));
  
  const arrLens = i =&gt; cons =&gt; xs =&gt;
    constMap(v =&gt; Object.assign([], xs, {[i]: v})) (cons(xs[i]));
  
  const view = fx =&gt;
    $$(runConst, fx(Const));
  
  const user = {name: "Bob", addresses: [
    {street: '99 Maple', zip: 94004, type: 'home'},
    {street: '2000 Sunset Blvd', zip: 90069, type: 'work'}]};
  
  // a lens
  const sndStreetLens =
    $$(objLens("addresses"), arrLens(1), objLens("street"));
  
  console.log(
    view(sndStreetLens) (user) // 2000 Sunset Blvd
  );</code></pre>
  </div>
  </div>
  </p>
  
  <p>In this version the functor constraint <code>constMap</code> is hard coded in the lens constructor. When <code>view</code> invokes a lens, the right type (<code>$$(runConst, fx(Const))</code>) is already passed, but in order to obtain an ad-hoc polymorphic lense, I need to pass the corresponding functor instance too.</p>
  
  <p>I already tried the most obvious thing <code>$$(runConst, fx(constMap) (Const))</code>, however, this interferes with the composition. I just can't figure it out.</p>