2010-07-08 4 views
8

Я пытаюсь написать общий interpolate метод, который работает на любом типе, который имеет два метода, * и +, как это:Scala - как определить структурный тип, который относится к самому себе?

trait Container { 
    type V = { 
    def *(t: Double): V 
    def +(v: V): V 
    } 

    def interpolate(t: Double, a: V, b: V): V = a * (1.0 - t) + b * t 
} 

Это не работает, хотя (по Scala 2.8.0 .RC7), появляется следующее сообщение об ошибках:

<console>:8: error: recursive method + needs result type 
      def +(v: V): V 
         ^
<console>:7: error: recursive method * needs result type 
      def *(t: Double): V 
          ^

Как правильно указать структурный тип? (Или есть лучший способ сделать это?)

+0

http://www.scala-notes.org/2010/06/avoid-structural-types-when-pimping-libraries/ может помочь здесь – VonC

+0

@VonC благодарит ... это мой собственный блог! ;-) – Jesper

+0

«© 2010 Jesper de Jong» ... riiiight. Ну, извините за это;) – VonC

ответ

8

Конечно, вы могли бы решить эту проблему с помощью классов типов подход (ЭГ Scalaz):

trait Multipliable[X] { 
    def *(d : Double) : X 
} 

trait Addable[X] { 
    def +(x : X) : X 
} 

trait Interpolable[X] extends Multipliable[X] with Addable[X] 

def interpolate[X <% Interpolable[X]](t : Double, a : X, b : X) 
    = a * (1.0 - t) + b * t 

Тогда, очевидно, вам потребуется (неявный) класс типов преобразования в области видимости для всех типов вы заботились о:

implicit def int2interpolable(i : Int) = new Interpolable[Int] { 
    def *(t : Double) = (i * t).toInt 
    def +(j : Int) = i + j 
} 

Тогда это может работать легко:

def main(args: Array[String]) { 
    import Interpolable._ 
    val i = 2 
    val j : Int = interpolate(i, 4, 5) 

    println(j) //prints 6 
} 
+0

Интересный подход, но он вызывает ошибку компилятора: http://gist.github.com/471620 – Jesper

+0

Извините - у меня нет доступа к действующему REPL на данный момент. Подход будет работать, возможно, всего несколько грубых краев, чтобы разобраться! –

+0

Похож, что проблема связана с двумя терминами 'a * (1.0 - t)' и 'b * t', которые производят' X', а затем вы делаете 'X + X' вместо' Interpolable [X ] + Interpolable [X] ', имплицитно не вызывается для' + 'по какой-либо причине. – Jesper

3

AFAIK, это невозможно. Это был один из моих собственных first questions.

+1

Действительно? Это меня удивляет, у Scala есть такая мощная система типов, но это невозможно. Благодарю. – Jesper

+0

@Jesper Я думаю, что я прочитал, что существует проблема с расхождением типа, связанная с поддержкой этого. –

Смежные вопросы