Je veux faire tous les types qui sont des instances de Enum
et Bounded
également des instances de Random
. Le code suivant fait cela, et devrait travailler (avec les extensions appropriées ont permis):Instances contraints par classe polymorphes
import System.Random
instance (Enum r, Bounded r) => Random r where
randomR (hi, lo) = inFst toEnum . randomR (fromEnum hi, fromEnum lo)
where inFst f (x,y) = (f x, y)
random = randomR (maxBound, minBound)
Mais je suis conscient que c'est mauvais style parce instance (Enum r, Bounded r) => Random r
crée une instance pour tous r
, juste avec des contrôles de type pour Enum
et Bounded
plutôt que Il suffit de mettre une instance sur les types Enum
et Bounded
. Cela signifie que je définis une instance pour tous les types :(
.
Le suppléant est que je dois écrire des fonctions autonomes qui me donnent le comportement que je veux et écrire un peu passe-partout pour chaque type que je veux être une instance de Random
:
randomBoundedEnum :: (Enum r, Bounded r, RandomGen g) => g -> (r, g)
randomBoundedEnum = randomRBoundedEnum (minBound, maxBound)
randomBoundedEnumR :: (Enum r, Bounded r, RandomGen g) => (r, r) -> g -> (r, g)
randomBoundedEnumR (hi, lo) = inFst toEnum . randomR (fromEnum hi, fromEnum lo)
where inFst f (x,y) = (f x, y)
data Side = Top | Right | Bottom | Left
deriving (Enum, Bounded)
-- Boilerplatey :(
instance Random Side where
randomR = randomBoundedEnumR
random = randomBoundedEnum
data Hygiene = Spotless | Normal | Scruffy | Grubby | Flithy
deriving (Enum, Bounded)
-- Boilerplatey, duplication :(
instance Random Hyigene where
randomR = randomBoundedEnumR
random = randomBoundedEnum
Existe-t-il des meilleures solutions de rechange? Comment devrais-je gérer ce problème? Ne devrais-je même pas essayer cela du tout? Suis-je trop inquiet à propos de la plaque?