tutorial software examples blanquerna bayer scala

software - Cómo paramaterizar Int según lo ordenado en Scala



scala wikipedia (2)

Tengo una clase con un tipo parametrizado en el que quiero hacer operadores de comparación. Asumo que necesito usar el rasgo Ordenado para lograr esto, pero al compilador no le gusta que lo use. Así que di que tengo la siguiente clase:

class Test[T <: Ordered[T]] { def someOp(t: T) if(t < 3) ... ... }

Sin embargo, si trato de usar esta clase de la siguiente manera:

val test = new Test[Int]()

El compilador se queja de la siguiente manera:

los argumentos de tipo [Prueba [Int]] no se ajustan a los límites del parámetro de tipo de prueba de la Prueba [T <: Ordenado [T]]

¿Puede alguien explicarme lo que estoy haciendo mal aquí?


Esto ocurre porque Int no es una subclase de Ordered[Int] (vea here por qué).

Sin embargo, existe una coerción implícita de Int a RichInt que es una subclase de Ordered[Int] , pero no se activa para los límites inferiores. Use <% (ver límites) en lugar de eso, que considerarán coerciones implícitas :

class Test[T <% Ordered[T]]


Puede utilizar la clase de tipo Ordering[T] como un parámetro implícito. Si quisieras escribir una función max genérica, se vería así:

def max[T](a:T, b:T)(implicit ordering:Ordering[T]) = { if(ordering.gt(a,b)) a else b }

Para los tipos de datos primitivos como Int, Float, ..., hay un ordenamiento implícito [T] en el alcance, por lo que puede usar esto como esperaría.

max(1,2) // gives 2

Para todos los tipos que implementan Ordered [T], también hay un implícito para proporcionar un Ordering [T].

También hay varios métodos en el alcance que combinan los pedidos. Por ejemplo, si tiene una N-tupla donde cada elemento tiene una Orden [T], existe automáticamente una Orden para el tipo de tupla.

max((1,2), (3,4)) // gives (3,4) because 3 is larger than 1

Pero si no está satisfecho con cualquiera de los pedidos proporcionados de forma implícita, solo puede escribir el suyo y pasarlo de manera explícita o incluso obtenerlo como un valor implícito . Me gusta esto:

val negativeIntOrdering = new Ordering[Int] { def compare(a:Int,b:Int) = b - a } max(1,2)(negativeIntOrdering) // gives 1

Por lo tanto, el enfoque basado en clases de tipos es mucho más flexible que el enfoque basado en la herencia. Esta es la razón por la cual las bibliotecas matemáticas como spire usan extensivamente.

Una cosa que no es tan agradable sobre el código anterior es que tiene que usar el método lt en lugar de un operador. Pero también hay una solución para eso. La ordenación tiene un método implícito llamado mkOrderingOps que proporciona operadores para T. Solo necesita tenerlo dentro del alcance al importar la ordenación._, de esta manera:

def max[T](a:T, b:T)(implicit ordering:Ordering[T]) = { import ordering._; if(a>b) a else b }