2014-04-09 3 views
3

커스텀 제네릭 unapply 함수에 내 평가자 감사를 응축하고 싶습니다.이 함수는 인수를 평가하고 성공하면 값을 반환합니다.스칼라 커스텀 제네릭으로 적용 취소

하지만이 오류 error: not found: type Eval

으로이 달성의 어떤 방법을 실패? 나는 typetags, implicit conversions for unapply methods을 보았습니다. 그러나 나는이 문제에서 어떻게 그들을 통합 할 수 있는지 보지 못합니다. 정확하게 Eval을 정의하는 방법?

 
object Test { 
    case class Context() 

    trait Expr 
    trait Literal[T] extends Expr{ 
    def value : T 
    } 
    case class IntLiteral(value: Int) extends Literal[Int] 
    case class StringLiteral(value: Int) extends Literal[Int] 
    case class Plus(e: Expr, f: Expr) extends Expr 

    object Eval { // Here I want the magic unapply to evaluate the expression. 
    def unapply[T](e: Expr)(implicit gctx: Context): Option[T] = { 
     eval(e) match { 
     case e: Literal[T] => Some(e.value) 
     case _ => None 
     } 
    } 
    } 

    def eval(e: Expr)(implicit c: Context): Expr = e match { 
    case Plus(Eval[Int](i), Eval[Int](j)) => IntLiteral(i+j) // Fails here. 
    case IntLiteral(i) => e 
    case StringLiteral(s) => e 
    } 

    eval(Plus(Plus(IntLiteral(1),IntLiteral(2)),IntLiteral(3)))(Context()) 
} 
+0

매우 관심이 ... –

답변

1

Eval[Int](...)은 단순히 합법적 인 패턴이 아니므로이 구문을 사용할 수 없습니다. 당신은 Eval 자체가 일반적인하고 유형의 인스턴스를 만들 수 원하는 수 있습니다

object Test { 
    case class Context() 

    trait Expr 
    trait Literal[T] extends Expr { 
    def value: T 
    } 
    case class IntLiteral(value: Int) extends Literal[Int] 
    case class StringLiteral(value: Int) extends Literal[Int] 
    case class Plus(e: Expr, f: Expr) extends Expr 

    case class Eval[T]() { 

    def unapply(e: Expr)(implicit gctx: Context): Option[T] = { 
     eval(e) match { 
     case e: Literal[T] => Some(e.value) 
     case _    => None 
     } 
    } 
    } 

    val IntEval = Eval[Int]() 

    def eval(e: Expr)(implicit c: Context): Expr = e match { 
    case Plus(IntEval(i), IntEval(j)) => IntLiteral(i + j) 

    case IntLiteral(i)    => e 
    case StringLiteral(s)    => e 
    } 

    println(eval(Plus(Plus(IntLiteral(1), IntLiteral(2)), IntLiteral(3)))(Context())) 
} 

을하지만,이 리터럴의 유형을 확인하지 않습니다! 여러분이이 원하는 경우에, 당신은 ClassTag이 필요하고 이것은 단지 : T하지 : Literal[T] 일치 수 있습니다 : 너무이 문제

object Test { 
    case class Context() 

    trait Expr 
    case class Literal[T](value: T) extends Expr // or case class Literal(value: Any) 
    case class Plus(e: Expr, f: Expr) extends Expr 

    case class Eval[T]()(implicit tag: scala.reflect.ClassTag[T]) { 

    def unapply(e: Expr)(implicit gctx: Context): Option[T] = { 
     eval(e) match { 
     case Literal(value: T) => Some(value) 
     case _    => None 
     } 
    } 
    } 

    val IntEval = Eval[Int]() 

    def eval(e: Expr)(implicit c: Context): Expr = e match { 
    case Plus(IntEval(i), IntEval(j)) => Literal(i + j) 

    case e: Literal[_]    => e 
    } 

    println(eval(Plus(Plus(Literal(1), Literal(2)), Literal(3)))(Context())) 
} 
관련 문제