Reputation: 147
I have these two function and my first functions calls the second one. The first one only acts as a kickstarter. Sadly I'm getting the following error.
runTo100 = rollDice 0 0
rollDice :: (Ord t, Show a, Random t, Num a, Num t) => t -> a -> IO ()
rollDice amount n = do
gen <- newStdGen
if amount <= 100
then do
let rolled = dice gen
rollDice (amount + rolled) (n + 1)
else do
putStrLn ("Rolls needed to reach 100: " ++ show n)
dice :: (Random a, RandomGen g, Num a) => g -> a
dice gen = head (take 1 $ randomRs (1, 6) gen)
Error:
Ambiguous type variable ‘t0’ arising from a use of ‘rollDice’
prevents the constraint ‘(Ord t0)’ from being solved.
Probable fix: use a type annotation to specify what ‘t0’ should be.
These potential instances exist:
instance (Ord a, Ord b) => Ord (Either a b)
-- Defined in ‘Data.Either’
instance Ord Ordering -- Defined in ‘GHC.Classes’
instance Ord Integer
-- Defined in ‘integer-gmp-1.0.2.0:GHC.Integer.Type’
...plus 23 others
...plus 89 instances involving out-of-scope types
(use -fprint-potential-instances to see them all)
• In the expression: rollDice 0 0
In an equation for ‘runTo100’: runTo100 = rollDice 0 0
|
119 | runTo100 = rollDice 0 0 | ^^^^^^^^^^^^
Why does this result in an ambiguous type error. I know that I have to specify a type somewhere, but I'm new to haskell and I don't fully understand what's going on. I looked at various posts but couldn't find any which helped me.
Thank you in advance for any help. :)
Upvotes: 0
Views: 72
Reputation: 3921
Get rid of the Random typeclass constraint, it seems superfluous.
rollDice :: (Ord t, Show a, Num a, Num t) => t -> a -> IO ()
Also, you need to either use the randomR
function and keep passing back the new generator you obtained from applying the function, OR use randomRs
as you do but retrieve a bunch of results (asking for 100 would guarantee having enough rolls to reach 100) then discard the rest of the rolls once your sum is past 100.
The way you wrote your code, no state is kept between rolls of the RNG, so you keep getting the same die roll over and over again. That is to say, if the first time you rolled the die, you got 4, then you will keep getting the number 4 until you reach a sum of 100.
As it is, your function would have an equal chance of printing the values 16, 20, 25, 33, 50 and 100. Can you confirm this?
Upvotes: 1
Reputation: 17786
The problem with your code is that GHC can find a number of types that could be used for t
. It has to be something that is an instance of Ord
, Random
and Num
. Unfortunately there are quite a few types that fit the bill. In fact most instances of Num
are also Random
and Ord
(Complex
is probably the only exception).
At this point GHC either has to guess or admit defeat. Having the compiler guess what you meant is generally considered a bad thing, so it reports the problem.
When you encounter an error like this you need to find somewhere in your code to tie down the exact type you want to use. As a rule this should be as far up the call stack as possible, which in this case is the type of rollDice
.
Upvotes: 2