Ok, now the analysis. Without the $, you get this error message (ghci 7.8.3):
Couldn't match type ‘g0 -> (a0, g0)’ with ‘(a, (a0, a0))’
Expected type: (a0, a0) -> (a, (a0, a0))
Actual type: (a0, a0) -> g0 -> (a0, g0)
Relevant bindings include
genThree :: t -> a (bound at /tmp/test.hs:6:1)
Probable cause: ‘randomR’ is applied to too few arguments
In the first argument of ‘state’, namely ‘randomR’
In a stmt of a 'do' block: state randomR (listMin, listMax)
The key line is "Probable cause: 'randomR' is applied to too few arguments". Since it takes and apparently has one argument, the most likely cause is that the expression isn't parsed the way you expect.. So make the parse explicit, which would be "state (randomR (listMin, listMax))". Using the $ operator does the same thing, and reads a bit cleaner once you get used to it.