我想要一个随机生成的6位数字.保证我永远不会将此功能调用超过1000次.每次调用它时,该函数应该能够返回不同的数字.
我想在nextRandom没有任何争论的情况下调用此函数.Haskell中有没有适合我的库?我不能保持种子.Haskell可以使用当前时间seed.
更新:问题的背景.
我正在生成一个图形(点格式),我想确保所有顶点都有不同的标签.我可以将生成时间作为标签附加,但我通过生成随机数来实现这一点.
纯函数(如nextRandom没有参数)就像数学函数.在每次调用时,它们使用相同的参数产生相同的结果.
所以你要求它是不可能的,因为
只需使用haskell方式,将种子或随机生成器传递给函数,或使用monad.如果有帮助,您可以提前创建1000个数字,然后从列表中检索它们.
你不能拥有一个每次都返回一个不同数字的纯函数.它的输出取决于它以前的调用,而不仅仅依赖于它的参数.但是你可以创建一个带有到目前为止生成的数字集的monad,然后重试生成一个随机数,直到它找到一个到目前为止尚未生成的数字.对于以下示例,我使用了MonadRandom包.
import Control.Monad
import Control.Monad.Random
import Control.Monad.State
import Data.IntSet (IntSet)
import qualified Data.IntSet as IS
import System.Random (getStdGen)
type RandDistinct g a = StateT IntSet (Rand g) a
evalDistinct :: RandomGen g => RandDistinct g a -> g -> a
evalDistinct k = evalRand (evalStateT k IS.empty)
Run Code Online (Sandbox Code Playgroud)
上述类型用于StateT增强随机数生成器以记住到目前为止生成的数字集.当我们想要评估这个monad中的计算时,我们从一个空集开始并用它来计算内部计算evalRand.
现在我们可以编写一个每次都返回一个不同数字的函数:
nextDistinct :: RandomGen g => (Int,Int) -> RandDistinct g Int
nextDistinct range = loop
where
-- Loop until we find a number not in the set
loop = do
set <- get
r <- getRandomR range
if IS.member r set
then loop -- repeat
else put (IS.insert r set) >> return r
Run Code Online (Sandbox Code Playgroud)
并测试它是如何工作的:
main = getStdGen >>= print . evalDistinct (replicateM 50 $ nextDistinct (10, 99))
Run Code Online (Sandbox Code Playgroud)
请注意,nextDistinct使用简单策略 - 如果集合中已存在新数字,则重试生成新数字.只要碰撞次数很少,这就可以正常工作.
| 归档时间: |
|
| 查看次数: |
617 次 |
| 最近记录: |