3 votes

comment définir un type structurel qui se réfère à lui-même ?

Je veux créer une méthode sum que je peux appeler sur différents types, spécifiquement sum(1,2).

def sum[A](a1: A, a2: A) = a1 + a2

Cela échoue parce que le compilateur ne peut pas dire si A a une méthode '+'.

J'ai essayé de définir un type de structure :

type Addable = {def +(a : Addable)}

Cela échoue à cause d'une référence cyclique illégale.

Comment puis-je réaliser cela de manière sûre sans exiger de A qu'il étende un trait spécifique ?

7voto

Daniel Spiewak Points 30706

Scala ne prend pas en charge les alias de types récursifs sans arguments supplémentaires du compilateur (spécifiquement, -Yrecursion ). Ceci est en partie pour garder le vérificateur de type au moins quelque peu dans le domaine de la décidabilité (bien que, comme nous l'avons découvert, le système de type est Turing Complete même sans alias de type récursif, donc cela n'a pas beaucoup d'importance).

La manière correcte de faire ce genre de choses est d'utiliser une classe de type. Scala les encode comme des limites de vue implicites. Par exemple :

trait Addable[A] {
  def zero: A
  def add(x: A, y: A): A
}

implicit object IntAddable extends Addable[Int] {
  def zero = 0
  def add(x: Int, y: Int) = x + y
}

implicit object DoubleAddable extends Addable[Double] {
  def zero = 0
  def add(x: Double, y: Double) = x + y
}

// ...

def sum[A](x: A, y: A)(implicit tc: Addable[A]) = tc.add(x, y)

Et bien sûr, cela vous permet aussi de faire des choses fantaisistes comme additionner le contenu d'un fichier Seq d'une manière sûre :

implicit def summableSeqSyntax[A](seq: Seq[A])(implicit tc: Addable[A]) = new {
  def sum = seq.foldLeft(tc.zero)(tc.add)
}

List(1, 2, 3, 4).sum        // => 10
List(true, false).sum       // does not compile

Il est intéressant de noter que Scala 2.8 a quelque chose de très proche de cela avec la fonction Numeric typeclass.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X