48 votes

Pourquoi l’inférence de type Scalas n’est-elle pas aussi puissante que celle de Haskells?

L'inférence de type moteur de Haskell est beaucoup plus puissant que Scalas. En Haskell, j'ai rarement à écrire explicitement les types alors qu'en Scala, les types ne peut être déduite dans les expressions, mais pas dans les définitions de méthode.

Voir, par exemple, suite à Haskell extrait de code:

size xs = loop xs 0
  where
    loop [] acc = acc
    loop (_ : xs) acc = loop xs (acc+1)

Il retourne la taille d'une Liste. Le compilateur Haskell peut reconnaître ce que les types sont utilisés et que la définition de la fonction est. L'équivalent de la Scala de code:

def size[A]: List[A] => Int = xs => {
  def loop: (List[A], Int) => Int = {
    case (Nil, acc) => acc
    case (_ :: xs, acc) => loop(xs, acc+1)
  }
  loop(xs, 0)
}

Ou avec les définitions de méthode:

def size[A](xs: List[A]) = {
  def loop(xs: List[A], acc: Int): Int = xs match {
    case Nil => acc
    case _ :: xs => loop(xs, acc+1)
  }
  loop(xs, 0)
}

Ma question est: Pourquoi ne puis-je pas écrire comme suit?

def size = xs => {
  def loop = {
    case (Nil, acc) => acc
    case (_ :: xs, acc) => loop(xs, acc+1)
  }
  loop(xs, 0)
}

Une fois de plus avec les définitions de méthode:

def size(xs) = {
  def loop(xs, acc) = xs match {
    case Nil => acc
    case _ :: xs => loop(xs, acc+1)
  }
  loop(xs, 0)
}

Est-ce parce que personne n'a encore mise en oeuvre? Est le type de système de Scala pas aussi puissant que nécessaire pour ce cas? Ou existe-il d'autres raisons?

59voto

hammar Points 89293

La raison principale est que le système de type de Scala permet de sous-typage, qui le Hindley-Milner algorithme d'inférence de types ne prend pas en charge.

Haskell n'a pas de sous-typage, de sorte que l'algorithme fonctionne beaucoup mieux, bien que de nombreux populaire type de système d'extensions prises en charge par le GHC cause l'inférence de type pour échouer à nouveau, vous forçant à fournir de type explicite signatures pour certaines expressions.

En fin de compte, c'est un compromis entre la puissance du système de type et le montant de l'inférence de type qui peut être fait. Scala, Haskell ont simplement fait des compromis différents.

30voto

Kipton Barros Points 12445

Je suppose que les principales raisons qui ont déjà été donné, mais je trouve cette citation par Scala, le créateur de Martin Odersky particulièrement instructif,

La raison de la Scala n'a pas de Hindley/Milner, l'inférence de type est que il est très difficile de combiner avec des fonctionnalités telles que la surcharge (la ad-hoc variante, pas de classes de type), de sélection d'enregistrement, et le sous-typage. Je ne dis pas impossible -, il existe un certain nombre d'extensions intégrer ces caractéristiques; en fait, j'ai été guitly de certains d'entre eux moi-même. Je dis juste qu'il est très difficile de faire que cela fonctionne bien pratique, où l'on a besoin d'avoir de petites expressions de type, et de la bonne les messages d'erreur. Ce n'est pas une ferme soit - de nombreux chercheurs sont travail à repousser les limites ici (regardez par exemple à Remy MLF). Mais pour l'instant il est un compromis de mieux le type d'inférence vs meilleur support de ces fonctions. Vous pouvez faire la différence à la fois façons. Le fait que nous voulions intégrer avec Java pencher la balance en faveur de sous-typage et loin de Hindley/Milner.

Source: commentaire sous le post Universelle de l'Inférence de Type est une Mauvaise Chose.

19voto

Owen Points 14439

hammar a donné la plus grande raison. Voici deux autres:

  • Scala utilise les types de résoudre les noms

Envisager

def foo(x) = x.a + x.b

Comment pourrait-Scala éventuellement déduire le type de l'argument? Faut-il regarder pour chaque classe avec un a et b domaine? Que faire si il y a plus de 1? En Haskell

foo x = (a x) + (b x)

enregistrer les noms sont uniques, qui présente ses propres problèmes, mais cela signifie que vous pouvez toujours déduire quel type de document il s'agit.

  • Pour votre exemple: case expressions en Scala peut être hétérogène

En Scala, le type de l'objet en cours d'appariement peut être utilisé soit comme une partie de la correspondance ou de décider de la façon de correspondance doit être fait. Donc, même si tous les constructeurs dans l' case sont pour l' List, vous pourriez voulez passer autre chose qu'une liste d'elle, et l'ont échouer.

14voto

Landei Points 30509

Une autre chose qui ne fonctionne pas bien avec l'inférence de type Hindley-Milner est la surcharge de méthodes et les fonctionnalités associées telles que les arguments par défaut et les variables variables. C'est pourquoi il est si difficile d'écrire des choses comme zipWithN en Haskell (qui est trivial en Scala).

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