Enum
のインスタンスであり、のインスタンスでBounded
もあるすべての型を作成したいと思いますRandom
。次のコードはこれを行い、動作するはずです (適切な拡張機能が有効になっている場合)。
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)
しかし、私はこれが悪いスタイルであることをinstance (Enum r, Bounded r) => Random r
認識r
しEnum
てBounded
います. これは事実上、すべてのタイプのインスタンスを定義していることを意味します。Enum
Bounded
:(
別の方法としては、必要な動作を提供するスタンドアロン関数を作成し、インスタンスにしたい各型のボイラープレートを作成する必要があります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
より良い代替手段はありますか?この問題をどのように管理すればよいですか? 私はこれを試みるべきではありませんか?ボイラープレートについて過度に心配していますか?