I have this function to generate a list of random values and get the generator back (if anyone knows a better way, feel free to leave it in the comments):
-- randomN :: (Random a, RandomGen g) => g -> Int -> ([a], g)
randomN gen n = (map fst rs, snd (last rs)) where
rs = take n (pool gen)
pool g = (r, g'):(pool g') where (r, g') = random g
I want to use it to shuffle lists. I created this function:
shuffle gen stuff = (map snd $ sortOn fst $ zip rs stuff, gen') where
rs :: [Int]
(rs, gen') = randomN gen (length stuff)
I understand that I need to explicitly instantiate rs, GHC will not magically figure how I want to sort the list.
Here is the question: my original attempt looked like this:
shuffle gen stuff = (map snd $ sortOn fst $ zip rs stuff, gen') where
(rs, gen') = randomN gen (length stuff) :: ([Int], g)
But that failed with the following error:
shuffle_minimal.hs:11:18: error:
• Couldn't match type ‘t1’ with ‘g’
because type variable ‘g’ would escape its scope
This (rigid, skolem) type variable is bound by
an expression type signature:
([Int], g)
at shuffle_minimal.hs:11:18-57
Expected type: ([Int], g)
Actual type: ([Int], t1)
• In the expression: randomN gen (length stuff) :: ([Int], g)
In a pattern binding:
(rs, gen') = randomN gen (length stuff) :: ([Int], g)
In an equation for ‘shuffle’:
shuffle gen stuff
= (map snd $ sortOn fst $ zip rs stuff, gen')
where
(rs, gen') = randomN gen (length stuff) :: ([Int], g)
• Relevant bindings include
gen :: t1 (bound at shuffle_minimal.hs:10:9)
shuffle :: t1 -> [b] -> ([b], t) (bound at shuffle_minimal.hs:10:1)
If the type variable is something as general as "g", how come the compiler is not able to match it with whatever other type?
What does "because type variable ‘g’ would escape its scope"? I have tried reading some other post but I do not really understand it :-(
Thanks!