title: Scala Type Mismatch underlying type and class vs method
body: <p>I'm implementing a class that acts as three stacks that rely on the same array (from Gayle Laakmann's cracking the coding interview). </p>
  
  <p>I'm having trouble understanding why this code results in type mismatches: </p>
  
  <pre><code>class ThreeStacks[A, B, C ](val stackSize:Int  = 1000) {
  
    /**
     * Push a value on to the first stack
     * @param value value of type A */
    def push1[A](value :A): Unit = stack1.push(value)
  
    /**
     * Push a value on to the second stack
     * @param value value of type B */
    def push2[B](value: B): Unit = stack2.push(value)
  
    /**
    * Push a value on to the third stack
    * @param value value of type C */
    def push3[C](value: C): Unit = stack3.push(value)
  
    /**
     * Pops the top value off the first stack
     * @return Some(value) at the top of the stack, None if the stack is empty */
    def pop1[A](): Option[A] = stack1.pop()
  
    /**
     * Pops the top value off the second stack
     * @return Some(value) at the top of the stack, None if the stack is empty */
    def pop2[B](): Option[B] = stack2.pop()
  
    /**
     * Pops the top value off the second stack
     * @return Some(value) at the top of the stack, None if the stack is empty */
    def pop3[C](): Option[C]  = stack3.pop()
  
    // the shared stacks
    private val stack1 = SharedStack[A]()
    private val stack2 = SharedStack[B]()
    private val stack3 = SharedStack[C]()
  
    // the shared stack class is simply a container for push and pop functions
    class SharedStack[T](val push: T =&gt; Unit, val pop: () =&gt; Option[T])
  
    // the sharedstack object is a factory setups a shared stack object with its proper push/pop functions that are received
    // from the stackmemory instance
    private object SharedStack{
      val stackMemory = new StackMemory(stackSize)
  
      def apply[T](): SharedStack[T] = {
        val stackTuple = stackMemory.registerStack[T]()
        new SharedStack(stackTuple._1, stackTuple._2)
      }
    }
  
  
    // the memory object responsible for handling the sharing of the array
    private class StackMemory(val stackSize: Int = 1000){
  
      // helps prevent the conflict warnings with immutable and mutable collections
      private val MutableMap = scala.collection.mutable.Map
  
      // the array that contains the stack nodes
      private val array = new Array[Option[StackNode[Any]]](stackSize)
  
  
      // keeps track of the heads of all the stacks
      private val registeredStackHeads = MutableMap[Int, Int]()
  
      // an index to help assign every new stack a unique key
      private var nextRegistrationIndex = 1
  
      // a list of indices in the array that have been freed
      private var freedIndices = List[Int]()
  
      // the next available free index, increments till it reaches the end of the array, different from the freeIndices list
      // in that it only is concerned with free cells while they are available at the end of the array
      private var nextFreeIndex = 0
  
  
      /**
       * Registers a stack within the memory object and returns the push/pop functions
       * @return the push/pop functions relevant for that stack */
      def registerStack[T](): (T  =&gt; Unit, () =&gt; Option[T]) = {
        val index = nextRegistrationIndex
        val noPreviousValueIndex = -1
  
        // register the index in the stack heads with an empty value
        registeredStackHeads(index) = noPreviousValueIndex
  
        nextRegistrationIndex += 1
        (push[T](index), pop[T](index) )
      }
  
      /**
       * Returns the push function for a stack at the given index
       * @param stackIndex the index of the requesting stack
       * @return  the push function for the stack */
      def push[T](stackIndex: Int) = {
        (value: T) =&gt;  {
  
          // get the indices and initialize a stack node
          val headIndex = registeredStackHeads(stackIndex)
          val index = nextAvailableIndex()
          val stackNode = new StackNode[T](headIndex, value)
  
          // store the new stack head and place it in to the array
          registeredStackHeads(stackIndex) = index
          array(index) = Some(stackNode)
        }
      }
  
      /**
       * The pop function for the stack at a given index
       * @param stackIndex  the index of the requesting stack
       * @return the pop function for the stack */
      def pop[T](stackIndex: Int): () =&gt; Option[T] = {
        () =&gt; {
          val headIndex = registeredStackHeads(stackIndex)
  
          if(headIndex &lt; 0) None else {
            array(headIndex) match {
              case Some(s : StackNode[T]) =&gt; {
                registeredStackHeads(stackIndex) = s.previousIndex
                freeIndex(headIndex)
                Some(s.value)
              }
              case _ =&gt; None
            }
          }
        }
      }
  
      // retrieve the next available index, throws an exception if there are no available indices
      private def nextAvailableIndex():Int = {
  
        // return a new index if the array isn't full otherwise throw an exception
        def newIndex() : Int = {
          if(nextFreeIndex &gt;= stackSize){
            throw new Exception("No more room in stack array available")
          }
          else{
            val index = nextFreeIndex
            nextFreeIndex += 1
            index
          }
        }
  
        // first check if any of the old indices have been freed
        freedIndices match {
          case Nil =&gt; newIndex()
          case head::tail =&gt; freedIndices = tail; head
        }
      }
  
      // frees an index and adds it to the free indices list
      private def freeIndex(i: Int): Unit = {
        if (i &gt;= array.length) throw new ArrayIndexOutOfBoundsException("The index to be freed does not exist in the array")
        array(i) = None
        freedIndices = i::freedIndices
      }
  
      // covariant node that helps keep track of the previous index of the stack
      private class StackNode[+S](val previousIndex: Int, val value: S)
  
    }
  }
  </code></pre>
  
  <p>The code works like its suppose to if I call stack1.push or stack1.pop but it causes type mismatches on wrappers push1 and pop1, why is this happenning? </p>
  
  <pre><code>example for push1: 
  type mismatch;
   found   : value.type (with underlying type A)
   required: A
    def push1[A](value :A): Unit = stack1.push(value)
  
  example for pop1: 
  type mismatch;
   found   : Option[A(in class ThreeStacks)]
   required: Option[A(in method pop1)]
   def pop1[A](): Option[A] = stack1.pop()
  </code></pre>