trait JavaApi { def isAuthenticated: Boolean } sealed trait IsAuthenticated object IsAuthenticated { def unapply(x: JavaApi): Option[IsAuthenticated] = if (x.isAuthenticated) Some(Yes) else Some(No) } case object Yes extends IsAuthenticated { def unapply(x: JavaApi): Option[Yes.type] = if (x.isAuthenticated) Some(Yes) else None } case object No extends IsAuthenticated { def unapply(x: JavaApi): Option[No.type] = if (x.isAuthenticated) None else Some(No) } def x: JavaApi = new JavaApi { override def isAuthenticated = true } def y: JavaApi = new JavaApi { override def isAuthenticated = false } // YES! x match { case IsAuthenticated(Yes) => println("YES!") case IsAuthenticated(No) => println("No. ):") } // YES! x match { case Yes(_) => println("YES!") case No(_) => println("No. ):") } // No. ): y match { case IsAuthenticated(Yes) => println("YES!") case IsAuthenticated(No) => println("No. ):") } // No. ): y match { case Yes(_) => println("YES!") case No(_) => println("No. ):") }