This page is no longer maintained — Please continue to the home page at www.scala-lang.org

Re: Implicit conversion to Functor

No replies
Sebastien Bocq
Joined: 2008-12-18,
User offline. Last seen 42 years 45 weeks ago.
Yup, that was the trick, thanks!

I declared Tree as an abstract class instead of a case class and then the compiler was able to flag my invalid match statement. Yet the compiler warns me that that my match statement is incomplete with a very strange message:

match is not exhaustive! missing combination $anon$1 missing combination $anon missing combination $anon missing combination $anon missing combination $anon$1 missing combination $anon$1 missing combination $anon$1 missing combination $anon$1 missing combination $anon$1 missing combination $anon$1 missing combination $anon$1 missing combination $anon missing combination $anon$1 missing combination $anon missing combination $anon missing combination $anon$1 missing combination
 $anon$1 missing combination $anon$1 missing combination $anon$1 missing combination $anon$1 missing combination $anon missing combination $anon missing combination $anon$1 missing combination $anon$1 missing combination $anon missing combination $anon$1

Is there a way to clear this warning while keeping Tree as a sealed class?

Here is the new code.

trait Functor[A, T[A]] {
  def fmap[B](f:A => B):T[B]
}

sealed abstract class Tree[A] {

  override def toString = {
      this match {
        case Leaf(x) => x.toString
        case Branch(a,b) => "[" + a + "," + b + "]"
        case _ => "Fck"
      }   
    }

}
case class Leaf[A](a:A) extends Tree[A]
case class Branch[A](a:Tree[A], b:Tree[A]) extends Tree[A]

object Tree {

  implicit def treeAsFunctor[A](t:Tree[A]):Tree[A] with Functor[A, Tree] = {
    new Tree[A] with Functor[A, Tree] {
      def fmap[B](f:A => B):Tree[B] = {
        t match { // Warning match is not exhaustive...
          case Leaf(x) => Leaf(f(x))
          case Branch(a,b) => Branch(a fmap f, b fmap f)
        }
      }   
    }
  }

}

object FunctorTest {
  def main(args : Array[String]) : Unit = {
    val t = Branch(Leaf(0), Branch(Leaf(1), Leaf(2)))
    println(t)
    // [0,[1,2]]
    println(t fmap(_+1))
  }
}

Thanks,
Sebastien

2008/12/24 Erkki Lindpere <erkki [at] lap [dot] ee>
In the implicit conversion you are creating a new class which is neither Leaf nor Branch, and so

*this* match {...}

can't match those patterns. I think you wanted

*t* match {...}

(to match the original node that is given as argument to the implicit conversion)

Sebastien Bocq wrote:
Hello,

I'm trying to convert an arbitrary type to a Functor using implicit conversions (see code below). it sounded like an interesting idea at the time but it absolutely doesn't work.

trait Functor[A, T[A]] {
 def fmap[B](f:A => B):T[B]
}

sealed case class Tree[A]() {
   override def toString = {
     this match {
       case Leaf(x) => x.toString
       case Branch(a,b) => "[" + a + "," + b + "]"
       case _ => "Fck" // Compiler complains that match is non exhaustive because
                     // "Tree[A] with Functor[A, Tree]" (see implicit conversion below)
                     // generates anonymous class Tree$$anon that extends Tree[A]
     }      }
 }

case class Leaf[A](a:A) extends Tree[A]
case class Branch[A](a:Tree[A], b:Tree[A]) extends Tree[A]

object Tree {
 implicit def treeAsFunctor[A](t:Tree[A]):Tree[A] with Functor[A, Tree] = {
   new Tree[A] with Functor[A, Tree] {
     def fmap[B](f:A => B):Tree[B] = {
       this match { // Line 27
         case Leaf(x) => Leaf(f(x))
         case Branch(a,b) => Branch(a fmap f, b fmap f)
         // Here the compiler does not complain that a case is missing, but it causes
         // the match error (compiler bug?)
       }
     }      }
 }
}

object FunctorTest {
 def main(args : Array[String]) : Unit = {
   val t = Branch(Leaf(0), Branch(Leaf(1), Leaf(2)))
   println(t)
   // [0,[1,2]]
   println(t fmap(_+1))
   // Exception in thread "main" scala.MatchError: Fck
   // at com.Tree$$anon$1.fmap(Functor.scala:27)
   // at com.Tree$$anon$1.fmap(Functor.scala:25)
   // at com.FunctorTest$.main(Functor.scala:41)
   // at com.FunctorTest.main(Functor.scala)
 }
}

Can someone explain me the match error and/or provide some suggestions to fix this code?

Thanks,
Sebastien


Copyright © 2012 École Polytechnique Fédérale de Lausanne (EPFL), Lausanne, Switzerland