This page states that the minimal complete definition of the Random class is "Nothing"
But if I don't provide them, they don't work:
data Color = Red | Blue deriving (Bounded, Show)
instance Random Color
yields the compiler warning:
test.hs:5:10: warning: [-Wmissing-methods]
• No explicit implementation for
‘randomR’ and ‘random’
• In the instance declaration for ‘Random Color’
|
5 | instance Random Color
and when I run the code I get an error:
*Main> let g = mkStdGen 100
*Main> (fst $ random g) :: Color
*** Exception: test.hs:5:10-21: No instance nor default method for class operation random
Why aren't random
and randomR
listed under the minimal complete definition?
CodePudding user response:
That is a good question. And the answer is: you are using an older version of random
, because starting with random-1.2
your code would not compile and would produce a compile time error, along the lines of:
• Could not deduce (UniformRange Color)
arising from a use of ‘System.Random.$dmrandomR’
from the context: RandomGen g
bound by the type signature for:
randomR :: forall g.
RandomGen g =>
Prior to random-1.2
there used to be no implementation for random
and randomR
, so compiler required implementation for those functions in a form of a compilation warning. However, starting with random-1.2 there is a default implementation that uses DefaultSignatures
extension, which means your instance Random Color
will compile without explicit implementation for random
and randomR
only if your type also has Uniform
and UniformRange
instances. For that reason compiler no longer shows random
and randomR
as required.
Edit
Starting with random-1.2.1
you can create an instance using nice helper functions uniformEnumM
and uniformEnumRM
:
import System.Random.Stateful
data Color = Red | Blue deriving (Bounded, Enum, Show)
instance Uniform Color where
uniformM = uniformEnumM
instance Uniform Color where
uniformRM = uniformEnumRM
instance Random Color