J'ai un type de données qui n'a de sens que si ses arguments peuvent être ordonnés, mais il me semble avoir besoin d'approfondir certains trucs complexes et potentiellement hacks pour le faire fonctionner (GADTs, principalement). Ce que je fais (les types de données contraints) est-il considéré comme une mauvaise pratique du haschell, et y a-t-il un moyen de contourner ce problème?Contexte dans les instances de données
Pour les intéressés, voici le code correspondant:
{-# LANGUAGE GADTs #-}
{-# LANGUAGE InstanceSigs #-}
import Data.List (sort)
data OrdTriple a where
OrdTriple :: (Ord a) => a -> a -> a -> OrdTriple a
instance Functor OrdTriple where
fmap :: (Ord a, Ord b) => (a -> b) -> OrdTriple a -> OrdTriple b
fmap f (OrdTriple n d x) = OrdTriple n' d' x'
where
[n', d', x'] = sort [f n, f d, f x]
Au début, je pensais que je venais de mettre un contexte dans l'instance Functor (c'est le seul exemple que je me bats avec), mais il semble que je ne peut pas (aucune mention du type contenu), et même si je pouvais encore avoir besoin de la contrainte sur fmap
que son type de retour puisse être commandé.
Comme il est, je reçois l'erreur suivante compilation, qu'il semble est parce que je suis trop contraignant l'instance Functor:
No instance for (Ord a)
Possible fix:
add (Ord a) to the context of
the type signature for
fmap :: (a -> b) -> OrdTriple a -> OrdTriple b
When checking that:
forall a b.
(Ord a, Ord b) =>
(a -> b) -> OrdTriple a -> OrdTriple b
is more polymorphic than:
forall a b. (a -> b) -> OrdTriple a -> OrdTriple b
When checking that instance signature for ‘fmap’
is more general than its signature in the class
Instance sig: forall a b.
(Ord a, Ord b) =>
(a -> b) -> OrdTriple a -> OrdTriple b
Class sig: forall a b. (a -> b) -> OrdTriple a -> OrdTriple b
In the instance declaration for ‘Functor OrdTriple’
Functor doit être applicable à tous les types, non seulement ceux qui sont contraints par 'Ord'. Vous ne pouvez pas le contraindre davantage même dans votre cas. C'est pourquoi les structures comme les arbres équilibrés ne peuvent pas non plus être des foncteurs. – bheklilr
Vous ne pouvez pas en faire un foncteur. La manière habituelle de contourner cela est alors de simplement implémenter une fonction "map" séparée, comme cela est fait pour 'Data.Set' et' Data.Map'. – Cubic