2009-03-27 7 views
14

Ich möchte eine Funktion schreiben, die auf jedem Scala-Typ mit einer Gesamtbestellung funktioniert (d. H. Ich kann '<' darauf verwenden). Wie lautet die Syntax dafür? Das Beste, was ich habe kommen mit istWie lautet die Scala-Syntax für eine Funktion, die einen Untertyp von Ordered [A] verwendet?

def lessThan[T <: Ordered[T]](x: T, Y: T) = x < y 

Das ist nicht, obwohl nicht funktioniert, wenn ich es aus dem REPL Versuchen Sie es mit:

scala> lessThan(1, 2) 
<console>:8: error: inferred type arguments [Int] do not conform to method lessThan's type parameter bounds [T <: Ordered[T]] 
     lessThan(1, 2) 
    ^

scala> import runtime._ 
import runtime._ 

scala> lessThan(new RichInt(1), new RichInt(2)) 
<console>:8: error: inferred type arguments [scala.runtime.RichInt] do not conform to method lessThan's type parameter bounds [T <: Ordered[T]] 
     lessThan(new RichInt(1), new RichInt(2)) 

Im Grunde glaube ich das Äquivalent von dieser wollen Haskell code:

lessThan :: (Ord a) => a -> a -> Bool 
lessThan x y = x < y 

Ich verwende scala 2.7.3 auf einem Debian-System.

Was vermisse ich und wo?

Antwort

24

Das Äquivalent von Haskells Typklassen in Scala erfolgt über implicits. Es gibt zwei Möglichkeiten zu tun, was Sie

wollen Die erste mit Blick Grenzen ist

scala> def lessThan[T <% Ordered[T]](x : T, y : T) = x < y 
lessThan: [T](T,T)(implicit (T) => Ordered[T])Boolean 

scala> lessThan(1,2) 
res0: Boolean = true 

Der zweite mit einem impliziten Parameter ist

scala> def lessThan[T](x : T, y : T)(implicit f : T => Ordered[T]) = x < y  
lessThan: [T](T,T)(implicit (T) => Ordered[T])Boolean 

scala> lessThan(4,3) 
res1: Boolean = false 

Ersteres ist Syntax Zucker für die spätere. Letzteres ermöglicht mehr Flexibilität.

+0

Warum müssen Sie das Implizit explizit als Parameter in die Methode einbringen? Wenn die scala-Laufzeitumgebung weiß, wie T implizit in Ordered [T] umgewandelt wird, warum muss ich einen impliziten Parameter auflisten? Vielen Dank! – shj

+2

Erstens kann man nicht einfach irgendein T in ein Ordered [T] umwandeln. Definieren Sie zum Beispiel eine Reihenfolge über (Int => Int). Zweitens, wenn eine Konvertierung möglich ist, kann die Laufzeit nicht konvertieren. Stattdessen weiß der Compiler, wie eine Funktion eingefügt wird, um die Konvertierung zur Laufzeit auszuführen. –

+0

sieht so aus, als ob die erste Methode veraltet ist [SI-7629] (https://issues.scala-lang.org/browse/SI-7629) –