为什么shuffle'函数需要一个Int参数?

时间:2018-10-06 12:27:38

标签: list haskell random shuffle

System.Random.Shuffle中,

shuffle' :: RandomGen gen => [a] -> Int -> gen -> [a]

hackage page将此Int引述为

  

...,它的长度,...

但是,似乎有一个简单的包装函数,如

shuffle'' x = shuffle' x (length x)

应该足够了。

2 个答案:

答案 0 :(得分:4)

findViewById(R.id.btn).setOnTouchListener(new View.OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { if (event.getAction() == MotionEvent.ACTION_DOWN) { // button pressed } else if (event.getAction() == MotionEvent.ACTION_UP) { // button relased. } return false; } }); 通过构建其输入列表的树形形式(包括树的大小)进行操作。 shuffle函数使用Data.Function.fix来执行此任务,但我还不太了解。以某种方式(我认为是由于buildTree而不是inner魔术的递归),它产生了一个平衡的树,然后具有对数查找。然后,它将使用此树,为每个提取的项目重建它。数据结构的优点是它只保留不可变形式的剩余项目;延迟更新可为它工作。但是在索引过程中,树的大小是必需的数据,因此无需单独传递它来生成用于构建置换的索引。 fix确实没有随机元素-它只是一个排列函数。 System.Random.Shuffle.shuffle的存在是使用其内部帮助程序shuffle'将其随机输入。因此rseq采用长度参数的原因似乎是因为他们根本不希望它触及列表参数。它仅传递到shuffle'中。

该任务最初似乎不太适合单链接列表。我可能会考虑改用VectorShuffling。我对为什么shuffle不在导出函数中感到困惑,因为它是使用随机数生成器构建排列的函数……反过来,使用{{3}可能会更好}。原因可能与历史有关,例如,稍后编写Data.Permute,而System.Random.Shuffle基于不可变随机访问队列的论文。

Data.Permute似乎具有更直接的基于Seq的随机播放功能。

答案 1 :(得分:3)

在给定列表的长度已知的情况下,可能不需要重新计算。因此,可以将其视为优化。

此外,通常,结果列表的大小不必与原始列表相同。因此,该参数可用于设置该长度。

这对于奥列格(Oleg)的原始想法是正确的(来源-http://okmij.org/ftp/Haskell/perfect-shuffle.txt):

-- examples

t1 = shuffle1 ['a','b','c','d','e'] [0,0,0,0]
-- "abcde"
-- Note, that rseq of all zeros leaves the sequence unperturbed.

t2 = shuffle1 ['a','b','c','d','e'] [4,3,2,1]
-- "edcba"
-- The rseq of (n-i | i<-[1..n-1]) reverses the original sequence of elements

但是,“ random-shuffle”软件包的实现并不相同:

> shuffle [0..10] [0,0,0,0]
[0,1,2,3random-shuffle.hs: [shuffle] called with lists of different lengths

我认为有必要跟软件包维护者进行跟进,以了解此功能的约定。