title: Aux Pattern for higher-kinded types
body: <p>EDIT: Here is a much simpler formulation of the problem, using <code>Foo</code> as an example of the <code>Aux</code> pattern which <em>does</em> work:</p>
  
  <pre><code>// Foo is a simple Aux-pattern type
  trait Foo[A, B] { type Out }
  
  object Foo {
    type Aux[A, B, C] = Foo[A, B] { type Out = C }
    // One instance, turning Int+String into Boolean
    implicit val instance: Foo.Aux[Int, String, Boolean] = null
  }
  
  // Wrapper is exactly the same but contains a higher-kinded type
  trait Wrapper[A, B] { type Contract[_] }
  
  object Wrapper {
    type Aux[A, B, C[_]] = Wrapper[A, B] { type Contract[_] = C[_] }
    // One instance, linking Int + String to Option
    implicit val instance: Wrapper.Aux[Int, String, Option] = null
  }
  
  // Same test for both
  def fooTest[A, B, C](implicit ev: Foo.Aux[A, B, C]): C = ???
  def wrapperTest[X[_]](implicit ev: Wrapper.Aux[Int, String, X]): X[Boolean] = ???
  
  // Compiles as expected
  fooTest: Boolean
  
  // Does not compile: could not find implicit value for parameter ev: Wrapper.Aux[Int,String,X]
  wrapperTest: Option[Boolean]
  
  // Does compile:
  wrapperTest(implicitly[Wrapper.Aux[Int, String, Option]]): Option[Boolean]
  </code></pre>
  
  <hr>
  
  <p>Old formulation of the question:</p>
  
  <p>Apologies for the convoluted example below. I essentially want to duplicate the <code>Aux</code> pattern for higher-kinded types.</p>
  
  <p>The scala:</p>
  
  <pre><code>// Foo is a normal Aux pattern calculation
  trait Foo[A, B] { type Out }
  
  object Foo {
    type Aux[A, B, C] = Foo[A, B] { type Out = C }
    // Foo turns Int + String into Boolean
    implicit val intInstance: Foo.Aux[Int, String, Boolean] = null
  }
  
  // Wrapper is supposed to be a type-level computation across
  // type-level functions
  // It takes two types and binds them with a contract (a nested
  // type-level function)
  trait Wrapper[A, B] { type Contract[X] }
  
  object Wrapper {
    type Aux[A, B, C[_]] = Wrapper[A, B] { type Contract[X] = C[X] }
  
    // It has one instance: It binds Int and String to the type-level
    // function Foo.
    implicit val fooWrapper: Wrapper.Aux[Int, String, Foo.Aux[Int, String, ?]] = null
  
  }
  
  object Testing {
  
    trait TestResult[X]
  
    // We summon a Contr, which is provided by Wrapper
    // The idea is we get the result of Foo's computation without summoning
    // Foo explicitly. This allows us to easily swap Foo out for another
    // Function if we desire
    implicit def testing[A, B, Contr[_], X](
      implicit wrapper: Wrapper.Aux[A, B, Contr],
      foo: Contr[X]
    ): TestResult[X] = ???
  
  
    // Compiles as expected
    implicitly[Wrapper.Aux[Int, String, Foo.Aux[Int, String, ?]]]
    implicitly[Wrapper[Int, String]]
    implicitly[Foo.Aux[Int, String, Boolean]]
    implicitly[Foo[Int, String]]
    val result1: TestResult[Boolean] = testing[Int, String, Foo.Aux[Int, String, ?], Boolean]
  
    // Does not compile
    val result2: TestResult[Boolean] = testing
    implicitly[TestResult[Boolean]]
  }
  </code></pre>
  
  <p>This is what I expect to happen in that last line:</p>
  
  <ul>
  <li>We're searching for a <code>TestResult[Boolean]</code></li>
  <li><code>testing</code> says we need a <code>Contr[Boolean]</code> for some <code>Contr</code> provided by <code>Wrapper</code></li>
  <li><code>Wrapper</code> gives a single instance of <code>Contr[_] = Foo.Aux[Int, String, ?]</code></li>
  <li>So compiler is searching for a <code>Foo.Aux[Int, String, Boolean]</code></li>
  <li>There is a single such instance provided by <code>Foo</code></li>
  <li>So the whole thing compiles</li>
  </ul>
  
  <p>Here is my <code>build.sbt</code> in case I am missing something:</p>
  
  <pre><code>scalaVersion := "2.12.6"
  
  scalacOptions := Seq(
    "-language:existentials",
    "-language:higherKinds",
    "-Ypartial-unification",  // EDIT
  )
  
  addCompilerPlugin("org.spire-math" %% "kind-projector" % "0.9.8")
  </code></pre>