1
votes

My requirement is to mixin trait depending on the type parameter of generic type. For this I am passing TypeTag as implicit parameter in apply method to fetch the Generic type.

This results in a following compile time error in map method :

not enough arguments for method apply:
(implicit tag: reflect.runtime.universe.TypeTag[B])customOption.AppOption[B] in object AppOption.

Unspecified value parameter tag.
No TypeTag available for B

Please suggest, what I am doing wrong with this approach, and if this approach is not fit for my requirement. New suggetions are welcome and will be appreciated.

Simplified code:

package customOption.withGenericMixins

import scala.reflect.runtime.universe._

sealed abstract class AppOption[+A] {
  def value: A
  def isEmpty: Boolean

  def map[B]( f: A => B ): AppOption[B] = {
    if ( !isEmpty ) {
      println( "map called : " + value )
    }

    //compile time error
    //not enough arguments for method apply: (implicit tag: reflect.runtime.universe.TypeTag[B])customOption.AppOption[B] in object AppOption.
    //Unspecified value parameter tag.
    //No TypeTag available for B
    if ( !isEmpty ) AppOption( f( this.value ) ) else AppOptionNone
  }
  def flatMap[B]( f: A => AppOption[B] ): AppOption[B] = {
    if ( !isEmpty ) {
      println( "flatMap called : " + value )
    }
    if ( !isEmpty ) f( this.value ) else AppOptionNone
  }
}

object AppOption {
  def apply[A]( value: A )( implicit tag: TypeTag[A] ): AppOption[A] = {
    if ( value == null ) {
      AppOptionNone
    } else {
      //Depending on the type, my requirement is to mixin Traits
      val genType = tag.tpe.toString
      genType match {
        case "String"  => new AppOptionSome( value ) //with XTrait
        case "Boolean" => new AppOptionSome( value ) //with YTrait
        case "Double"  => new AppOptionSome( value ) //with ZTrait
        case _         => throw new RuntimeException( s"$genType not supported by AppOption" )
      }

    }
  }
}

case class AppOptionSome[+A]( value: A ) extends AppOption[A] {
  def isEmpty = false
}

case object AppOptionNone extends AppOption[Nothing] {

  def value = throw new NoSuchElementException( "AppOptionNone.value" )
  def isEmpty = true
}
1

1 Answers

0
votes

Please suggest, what I am doing wrong with this approach

If you require apply[A](value: A) to have an implicit TypeTag, you need to make sure your map[B] has the same requirement:

def map[B: TypeTag](f: A => B): AppOption[B]

As map will call apply and needs the said TypeTag to be available.