Y a-t-il un type de scala idiomatique pour limiter une valeur de point flottante à une plage de flottille donnée définie par une limite inférieure supérieure?
Béton Je veux avoir un type de flotteur uniquement autorisé à avoir des valeurs comprises entre 0.0. et 1.0. P>
plus concret Je suis sur le point d'écrire une fonction qui prend une fonction Int et une autre fonction qui correspond à celle de la plage entre 0.0 et 1,0, en pseudo-scala: P>
def foo(x : Int, f : (Int => {0.0,...,1.0})) {
// ....
}
3 Réponses :
Je ne saurais pas comment le faire statiquement, sauf avec types dépendants em> ( Exemple ), quelle scala n'a pas. Si vous avez uniquement traité des constantes, il devrait être possible d'utiliser des macros ou un plug-in compilateur qui effectue les chèques nécessaires, mais si vous avez des expressions typées de float arbitraires, il est très probable que vous ayez à recourir à des contrôles d'exécution. Voici une approche. Définissez une classe qui effectue une vérification d'exécution pour vous assurer que la valeur du flotteur est dans la plage requise: p> Vous pouvez l'utiliser comme suit: p> ou comme: p> Ce serait bien si on pouvait utiliser Voici un argument intuitif Pourquoi les types en fonction des nombres naturels peuvent être codés dans un système de type qui ne supporte pas (entièrement) dépendant Types em>, mais des flotteurs à distance ne peuvent probablement pas: les nombres naturels sont un ensemble énumérable, ce qui permet d'encoder chaque élément comme Types dépendant du chemin à l'aide de numéros de PEERO . Les nombres réels, cependant, ne sont plus énormes, et il n'est donc plus possible de créer systématiquement des types correspondant à chaque élément des réels. P> Maintenant, des flotteurs informatiques et des réels sont éventuellement des ensembles finis, mais Toujours un moyen d'être important d'être raisonnablement soumis à un système de type. L'ensemble de nombres naturels informatiques est bien sûr également très important et pose donc un problème pour l'arithmétique sur les chiffres de PEERNO codé en tant que types, voir le dernier paragraphe de Cet article . Cependant, je prétends qu'il suffit souvent de travailler avec le premier n em> (pour un nombre plutôt petit n em>), comme, par exemple, en évidence par nécessite code> dans le constructeur (actuellement) interdit. p>
edit: strong> Adressage des commentaires par @paradigmatic p>
Il convient de noter que même si Scala avait des types dépendants pouvant exprimer cela, cela viendrait à un coût énorme. Les personnes qui veulent souvent des types restreints ne pensent souvent pas à la charge supplémentaire de la production de valeurs de ces types. Quelqu'un vous donne un float d'entrée? Assurez-vous d'avoir une procédure de test qui produit un flotteur dans votre gamme ou vous indique qu'il ne correspond pas. Faire des mathématiques compliquées sur une collection de flotteurs dont le résultat peut être montré? Vous devrez écrire une longue preuve (dans la langue) que le résultat s'adaptera toujours dans la gamme. Personnellement, j'adore le faire, mais c'est dur ...
Il y a dépend des types de Scala. Regardez la première réponse: Stackoverflow.com/Questtions/12935731/...
@paradigmatic jamais essayé d'encoder des flotteurs à distance (pas de Nats) avec ce que Scala offre à cet égard? Faites-moi savoir si vous réussissez.
@MHS n'a jamais essayé (et ne le fera jamais). Mais malgré des limitations, il y a des types dépendants dans Scala et prétendant prétendre que le contraire est faux. Cependant, votre réponse a toujours un sens.
@paradigmatic, je suis sûrement d'accord pour dire que Scala prend en charge les types de dépendants i> PATH i>, mais je ne suis pas convaincu que celles-ci vous permettent de coder tout ce type de dépendant général vous permettant d'exprimer. Par exemple, des flotteurs variés. Et je ne suis pas le seul à avoir des doutes, voir les commentaires de SCLV à la réponse que vous avez référencée.
@ PARADADIGMATIQUE Les types dépendants du chemin ne sont pas vraiment quels types de théoriciens signifient quand ils disent des types dépendants. Le point de base est que vous ne peut pas i> encoder cette notion de flotteur à distance à l'aide de PDTS et peut utiliser DTS. Vous pouvez "soulever" un gros morceau de ce que signifie être un float code> et le refléter au niveau du type, mais vous pouvez le faire dans des langues avec beaucoup de systèmes de type plus faible, donc je ne suis pas Bien sûr, c'est un critère particulièrement précieux. Tout comme des miles a fait dans sa réponse, je peux appeler une fonction de haskell f :: quelquegadt a -> A code> un "type PI" et pendant que cela dispose de certaines caractéristiques, ce n'est pas la même chose.
Je ne sais pas pourquoi les gens Scala sont si défensives à propos de ce sujet (c'est absolument en disant que quiconque le contraire est «faux» sans comprendre la théorie de type sous-jacente). Personne ne résolvait la génialité du système de type de Scala. De nombreux types dépendants que les gens aiment toujours faire des trucs fous avec le niveau de type de Haskell, et une grande partie de cela est efficacement des types dépendants, mais vous n'êtes toujours pas en réalité en fonction des valeurs. C'est cool et puissant, mais si vous commencez à parler de "types dépendants limités", c ++ convient également à la facture, et je ne vois pas le point de confusion de la terminologie.
Aurait-il été moins controversé si mon commentaire avait déclaré: «Il convient de noter que même si Scala pourrait I> exprimer cela, cela viendrait à un coût énorme» sans mentionner le terme DT chargé? La signification est la même, car Scala ne peut pas exprimer un type de flotteur à distance. Agda peut. Appelez la distinction ce que vous voulez.
@paradigmatic J'ai ajouté un paragraphe faisant un argument intuitif Pourquoi les chiffres naturels peuvent être traités, mais les réels ne peuvent pas.
@mhs merci pour l'explication, je vous ai enfin compris que vous aviez le point.
@MHS Je pense que la déclaration la plus précise est de savoir si un type est inductif / données ou non. Les naturels sont inductifs et les Hlistes sont aussi; Les réels ne sont pas, et les flux ne sont pas non plus. Le fait que nous puissions avoir des fonctions de type de type raisonnablement arbitraires suggère que nous pouvons probablement faire des trucs cotinés aussi, cependant. Un codage des rationnels est en tant que paire d'un entier et d'un codage naturel et un codage des réels est fonction des rationnels aux rationnels. Malheureusement, les fonctions de type Scala doivent principalement être écrites en pseudo-cps car vous ne pouvez pas utiliser directement des types.
Voici une autre approche en utilisant un Classe implicite em>: Il nécessite un indice de compilateur d'utiliser la classe implicite, soit en tapant explicitement les Summands explicitement ou En choisissant une méthode qui n'est pas fournie par le flotteur Scala. P> De cette façon, au moins, les chèques sont centralisés, vous pouvez ainsi l'éteindre, si la performance est un problème. Comme l'a souligné MHS, si cette classe est convertie en une classe de valeur implicite em>, les chèques doivent être supprimés du constructeur. P> J'ai ajouté @inline annotations, mais je suis Pas sûr, si cela est utile / nécessaire avec classes implicites em>. p> Enfin, je n'ai eu aucun succès pour ignorer le flotteur Scala "+" avec P> import scala.{Float => RealFloat}
import scala.Predef.{float2Float => _}
import scala.Predef.{Float2float => _}
Vous pouvez utiliser des classes de valeur comme indiquées par MHS em>: Ils doivent être créés à l'aide de la méthode d'usine de l'objet compagnon, qui vérifiera que la gamme est correct: p> Cependant, en utilisant des opérations qui ne produira jamais un nombre en dehors de la plage ne nécessiteront pas de contrôle de validité. Par exemple * code> ou opposé code>. P> p>
Je ne savais pas que les classes de cas peuvent prolonger NONVAL. Cool!
.. Ainsi MHS obtient la tique, de toute façon la vôtre est assez propre, merci!
Avez-vous regardé Spire ?
semble prometteur, va vérifier!