2012-08-15 4 views
1

Je suis en train de faire de ce type de données auquel une instance de Functor:Est-il impossible de créer une instance Functor de ce type de données?

data Fraction = Frac Integer Integer deriving Show 

Mais, en le définissant comme cela ne fonctionnera pas:

instance Functor Fraction where 
    pure = Frac 1 1 
    fmap f (Frac a b) = Frac (f a) (f b) 

Je veux cette fonctionnalité, et je préfèrent que les données soient une instance de Functor. Mais, est-ce que cela viole certaines lois puisque les paramètres de Fraction sont toujours deux Integers?

Je pourrais toujours écrire fmap seul et éviter la déclaration Functor, mais j'essaie de me familiariser avec la langue, donc toute aide serait appréciée!

Répondre

8

Oui, vous ne pouvez pas définir un foncteur sans avoir une variable de type à "laisser de côté" pour la déclaration (Ou plus formellement: une instance de foncteur doit être définie pour quelque chose de genre * -> *). La signature de fmap est fmap :: (a -> b) -> f a -> f b, donc afin de satisfaire ce contrat, il doit être possible de choisir tous les types a et b pour la fonction.

Vous pouvez bien sûr simplement redéfinissez Fraction être ceci:

data Fraction a = Frac a a deriving Show 

... ou vous pouvez utiliser le type de données existantes pour les fractions/nombres rationnels Data.Ratio, qui ne forme pas un foncteur parce que personne ne a jugé utile d'avoir une telle instance (de quoi l'utiliseriez-vous, de toute façon?), mais au moins vous utiliseriez une structure de données existante et bien établie.

+0

Je construis une petite bibliothèque pour une sorte d'exercice. 'fmap' ne peut même pas être utile du tout ... Je suppose que c'est un bon point. Mais, en tout cas, merci pour la clarification! Cela m'aide beaucoup. –

+1

La seule utilisation de 'fmap' que je vois est qu'il pourrait être utilisé pour diviser le numérateur et le dénominateur par une valeur commune, mais c'est assez facile à faire avec, par exemple, correspondance de motif. Aussi, je pense que le plus grand signe que quelque chose ne va pas est qu'il n'y a pas de manière sensée d'implémenter 'pure' pour' Fraction', même si elle était contrainte à utiliser seulement 'Integer'. Pourquoi le numéro «1/1» est-il spécial? Pourquoi pas "0/12" ou "42/1"? Mais vous pourriez être intéressé par la classe de type 'Monoid', et les différentes classes dans le paquet [' algebra'] (http://hackage.haskell.org/package/algebra). – dflemstr

+0

(Pour le paquet d'algèbre, vous devrez peut-être cliquer sur une version précédente pour lire la documentation, car la dernière version est gloutée et manque de documentation) – dflemstr

Questions connexes