disons que je veux écrire une fonction pour décider si un numéro entier donné est prime, que Signature de type forte> dois-je utiliser? isPrime :: (Integral a) => a -> Bool
3 Réponses :
Le type Le type Les formulaires génériques utilisant Ce que vous voudrez peut-être envisager dans votre cas est à la place du type Si la mémoire me sert, les seules instances de int -> bool code> signifie que votre fonction fonctionne sur des valeurs de type int code>, qui sont des entiers limités de taille (la taille maximale étant, je crois, machine -dépendant). p>
(intégral A) => a -> bool code> signifie que votre fonction fonctionne sur des valeurs de tout type em> qui a une instance du intégrale < / Code> Classe de type - c'est-à-dire des types qui se comportent comme des entiers em> d'une manière particulière. La principale raison de choisir cela sur un type concret consiste à créer une fonction plus générale. p>
intégrale code> ont tendance à être très utiles lorsque vous devez travailler avec des types d'entier dans d'autres contextes - un bon exemple d'être des endroits où la bibliothèque standard échoue em> > faire, par exemple Fonctions telles que Replicat :: int -> a -> [a] code>. Code qui fonctionne sur un type de type entier spécifique à ses propres fins qui souhaite utiliser ce type avec Repliquer code> doivent donc convertir en int code> d'abord, ou importer générique code> à partir de data.list code>. p>
entier code>, qui représente des entiers de taille arbitraire. Puisque votre objectif principal est le calcul, il existe moins de valeur pour supporter des types d'intégrale arbitraires. P>
intégrale code> dans la bibliothèque standard sont int code> et integer code> de toute façon. ( EDIT FORT>: Comme Hammar me rappelle dans les commentaires, il existe également des instances pour les types de taille fixe dans data.int code> et data.word code>. Il existe également des types étrangers tels que cint code> mais je ne tiens pas compte des personnes intentionnellement.) P>
Il existe également les taille fixe dans data.int code> et data.word code>.
@hammar: Ah, droite! J'ai oublié ceux qui font réellement partie des bibliothèques standard, merci.
Troisième option: Définir une classe de caractères Class Hasprimes A Où Isprime :: A -> Bool Code> vous permettrait de définir un algorithme de primalité différent pour chaque type. Vous pouvez même définir une instance par défaut intégrale A => HASPRimes A Où ... code> avec un algorithme général. L'avantage est que si vous avez eu un algorithme plus efficace pour un type particulier, vous pouvez également l'utiliser, de sorte que ce serait le meilleur des deux mondes.
@rampion L'instance par défaut est imo une mauvaise idée, comme cela nécessiterait chevauchant des contextes code>. La classe est une bonne idée.
@Danielfischer: Je suppose que instance hasprimes entier code> et isintationgalPrime :: Integral A => A -> Bool; isintgralprime = isprime. totinteger code> suffirait plutôt qu'une instance par défaut.
@Rampion Oui, je pense que cela ferait bien.
@DANIELFISCHER: Ou si vous vouliez restreindre hasprimes code> à intégral code> Types, vous pouvez utiliser une implémentation par défaut dans la classe elle-même: classe intégrale A => haleprimes a où isprime :: a -> bool; isprime = isIntegerprime. totinteger code>
De nombreux tests de primalité sont probabilistes et ont besoin de nombres aléatoires, donc au moins au niveau le plus bas, ils auraient une signature de type comme celle-ci: une contrainte intégrale semble raisonnable, parce que vous faites généralement Pas besoin d'un type de béton, mais uniquement des opérations telles que REM code>. p> p>
Eh bien, un test probabiliste aurait besoin d'un type de retour monadique: semble-être :: (intégrale a) => a -> [a] -> io bool code>
Je recommanderais la signature une signature Un type ou envisager des types finis Modélisation d'une bague de facteur Donc, le seul test significatif et réalisable est: "Est-ce une prime rationnelle (ou naturelle) dont la valeur se trouve dans la gamme du type?" . Qui est capturé (aussi bon que possible sans sacrifier trop de vitesse) dans le type isprime :: int -> bool code> exclurait des tests rapides pour les nombres de largish, car ces tests débordaient souvent alors (Techniquement, c'est aussi vrai de entier code>, au moins dans la version fournie par INTEGER-GMP code>, mais vous serez probablement hors de mémoire long em > Avant cela importe, nous pouvons donc maintenir la fiction d'un type INEGER code> Integer code>). P> isprime :: Integral A => A -> BOOL code> serait un mensonge avec une implémentation réalisable. On pourrait avoir une instance de intégrale code> pour une modélisation de type z [sqrt (2)] code> (bien que pour un tel type totinteger code> serait infidèle) , pour un tel type, 2 ne serait pas un premier, comment détecterait-on qu'avec un test générique? p> z / (n) code> . Une instance ord code> pour ces types serait incompatible avec l'arithmétique, mais nous avons déjà cela pour int code>, etc., par exemple, dans z (6) = {0 , 1,2,3,4,5} code>, le Primes serait 2 , 3 et 4 (Notez que rien d'entre eux n'est irréductible , 2 = 4 * 2, 3 = 3 * 3, 4 = 2 * 2). P> isprime :: entier -> bool code>, pour être combiné avec un TOINTEGER code> le cas échéant. p> p>
Ce n'est pas à propos de ma question mais pourquoi 5 est-il un premier depuis 5 est non-zéro non-unité et 5 | 1 * 5 => 5 | 5 code>; aussi pourquoi 2 et 3 ne sont pas irréductibles
5 est une unité, 5 * 5 = 1 code>. Et nous pouvons écrire 2 = 4 * 2 code>, ni 4 ni 2 être une unité, et 3 = 3 * 3 code>, ni 3 ni 3 être une unité, donc 2 et 3 sont réductibles. D'autre part, si 2 divise a * b code> alors 2 doit déjà diviser A code> ou B code> (qui est hérité de z), donc 2 est une principale (alternativement, (z / 6) / 2 ~ z / 3 code>, la bague de facteur de z / (6) code> par l'idéal généré par 2 est le champ z / (3) code>, en particulier un domaine intégral). Similaire pour 3.
Je pense que je ferais mieux de me tourner vers un livre sur l'algèbre abstrait plutôt que de vous déranger avec des concepts de base ici; Vous pensez donc que nous ne pouvons pas traiter de telles choses avec Haskell ou avec d'autres langages de programmation?
Oh, ces concepts ne sont pas si basiques. Mais un bon livre est certainement un meilleur moyen de l'apprendre - si vous voulez - que l'espace limité dans les commentaires. Traiter avec de telles choses n'est pas trivial, la classe intégrale code> n'est pas la bonne façon pour cela, mais la remparte proposé un hasprimes code> classe dans les commentaires pour C.A. La réponse de McCann, alors chaque instance serait responsable du bon comportement dans ce cas. Notez que les nombres premiers dans les anneaux avec des diviseurs de zéro comme z / (6) code> ne sont pas très intéressants. Mais l'autre exemple ou des anneaux polynomiaux sont intéressants et ne correspondent pas au corset intégrale code>.