Werfen Sie einen Blick auf https://github.com/fthomas/refined. Sie können vorhandene Typen auf Typenebene verfeinern (einschränken). Z.B. positive ganze Zahlen, die immer noch eine Untertypbeziehung mit ganzen Zahlen haben.
Die Syntax ist ein wenig ausführlich, und es wird Box-Primitiven (siehe unten für Details). Aber ansonsten macht es genau das, was du willst.
Hier ist eine kurze Demo. Definieren Sie eine Verfeinerung und ein Verfahren eine raffinierte Art mit:
import eu.timepit.refined._
import eu.timepit.refined.api.Refined
import eu.timepit.refined.auto._
import eu.timepit.refined.numeric._
type FiveToFifteen = GreaterEqual[W.`5`.T] And Less[W.`15`.T]
type IntFiveToFifteen = Int Refined FiveToFifteen
def sum(a: IntFiveToFifteen, b: IntFiveToFifteen): Int = a + b
Verwenden Sie es mit Konstanten (man beachte die gute Kompilierung Fehlermeldungen):
scala> sum(5,5)
res6: Int = 10
scala> sum(0,10)
<console>:60: error: Left predicate of (!(0 < 5) && (0 < 15)) failed: Predicate (0 < 5) did not fail.
sum(0,10)
^
scala> sum(5,20)
<console>:60: error: Right predicate of (!(20 < 5) && (20 < 15)) failed: Predicate failed: (20 < 15).
sum(5,20)
^
Wenn Sie Variablen haben, wissen Sie nicht, bei der Kompilierung ob sie in Reichweite sind oder nicht. So kann das Downcasting von Int zu einem verfeinerten Int fehlschlagen. Das Auslösen von Ausnahmen wird in funktionalen Bibliotheken nicht als guter Stil angesehen. So ist die refineV Methode gibt ein Entweder:
val x = 20
val y = 5
scala> refineV[FiveToFifteen](x)
res14: Either[String,eu.timepit.refined.api.Refined[Int,FiveToFifteen]] = Left(Right predicate of (!(20 < 5) && (20 < 15)) failed: Predicate failed: (20 < 15).)
scala> refineV[FiveToFifteen](y)
res16: Either[String,eu.timepit.refined.api.Refined[Int,FiveToFifteen]] = Right(5)
Rüdiger, könnten Sie sich bitte diese Frage ansehen? http://stackoverflow.com/q/37944150/226895 – expert