Question

J'ai un type de données pour polynomiale r polynômes en Haskell et une instance Anneau pour elle. . (Le class Ring r where plus :: r -> r -> r ; times :: r -> r -> r ; negative :: r -> r ; zero :: r ; one :: r - c'est juste une version simplifiée du Num)

Maintenant, je pourrais définir un polynôme tel que gauss = x^2 + 1 ou eisenstein = x^2 + x + 1 puis travailler dans « polynomiale Entier / (gauss) » pour les entiers de Gauss ou « polynomiale Entier / (Eisenstein) » pour les entiers d'Eisenstein. C'est le problème, je l'ai écrit entre guillemets parce que ce n'est pas un vrai type de données, et je ne peux pas comprendre comment le définir.

J'ai d'abord essayé de faire quelque chose comme data Quotient p = Quot p p et par exemple nous aurions plus (Quot a i) (Quot b i') | i == i' = Quot (plus a b) i Bien sûr, cela est assez mal déjà, mais il est encore impossible de définir one et zero. Alors je l'ai changé pour data Quotient p = Quot p (Maybe p) et je pense avoir une implémentation de travail en utilisant cela, mais vous ne savez jamais sûr si plus fonctionnera (il a besoin d'au moins un Just, et s'il y en a deux, ils doivent être les mêmes).

est-il un type sûr (je veux dire ne pas utiliser les fonctions dangereuses) façon de programmer cela dans haskell? Je suis assez perplexe. Merci!

Était-ce utile?

La solution

configurations implicites papier (cabalized ) utilise quotients de Z à titre d'exemple; il devrait être facile de l'adapter à des anneaux polynôme (à moins que je me manque quelque chose).

Modifier: Ne pas dire les configurations implicites se sont simples, loin de là;) - juste la modification

.

Autres conseils

Peut-être que vous pourriez augmenter votre type polynôme avec un index ou une étiquette? Si je comprends bien, votre module normale serait quelque chose comme:

data Poly r = Poly r

class Ring r where
  plus :: r -> r -> r
  times :: r -> r -> r

instance Ring (Poly Integer) where
  plus (Poly x) (Poly y) = Poly (x + y)
  times (Poly x) (Poly y) = Poly (x * y)

gauss :: Poly Integer
gauss = Poly 1

eins :: Poly Integer
eins = Poly 2

Et vous voulez être en mesure de différentiel en toute sécurité entre les deux « sous-types » des anneaux. Peut-être que vous pouvez les marquer comme ceci:

newtype PolyI i r = PolyI r

instance Show r => Show (PolyI i r) where
  show (PolyI p) = show p

instance Ring (PolyI i Integer) where
  plus (PolyI x) (PolyI y) = PolyI (x + y)
  times (PolyI x) (PolyI y) = PolyI (x * y)

Nos instances de l'anneau exigent maintenant un i type argument supplémentaire que nous pouvons créer en ayant de simples types non-constructeur.

data Gauss
data Eins

Ensuite, nous créons simplement les polynômes spécifiques avec l'index comme argument:

gaussI :: PolyI Gauss Integer
gaussI = PolyI 11

einsI :: PolyI Eins Integer
einsI = PolyI 20

Avec l'instance Show ci-dessus, nous obtenons le résultat suivant:

*Poly> plus einsI einsI
40

et

*Poly> plus einsI gaussI

Couldn't match expected type `Eins' with actual type `Gauss'
Expected type: PolyI Eins Integer
  Actual type: PolyI Gauss Integer
In the second argument of `plus', namely `gaussI'

Est-ce quelque chose comme ce que vous cherchez?

Modifier après un commentaire à la question sur newtype, je pense que cela peut aussi une solution élégante si vous utilisez NewtypeDeriving pour alléger le fardeau de réimplémenter l'instance Poly Integer. Je pense à la fin, il serait similaire, si un peu plus élégant que cette approche.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top