如何打乱列表?

2024-05-19

如何从一组数字([1, 2, 3])直到我击中x? 我的计划是重新调整列表[1, 2, 3]并把它砍在x:

-- chopAt 3 [2, 3, 1] == [2, 3]
-- chopAt 3 [2, 1, 3] == [2, 1, 3]
-- chopAt 3 [3, 1, 2] == [3]
chopAt _ [] = []
chopAt x (y:ys)
  | x /= y    = y : chopAt x ys
  | otherwise = [y]

然而我不知道如何洗牌列表(或理解 Monads)。

-- sample without replacement from [1, 2, 3] until one hits a 3
-- x <- shuffle [1, 2, 3]
-- print (chopAt 3 x)
main = do
-- shuffle [1, 2, 3]
  print (chopAt 3 [1, 3, 2])

Use random http://hackage.haskell.org/packages/archive/random/1.0.0.3/doc/html/System-Random.html甚至也许莫纳德随机 http://hackage.haskell.org/packages/archive/MonadRandom/0.1.3/doc/html/Control-Monad-Random.html来实施你的洗牌。存在一些好的答案here http://www.haskell.org/haskellwiki/Random_shuffle

但这确实是可操作的。这是幕后发生的事情。

I.

随机性是 Haskell 中你首先遇到并且必须处理杂质的地方之一——这似乎很令人反感,因为洗牌和样本看起来很简单,而且感觉它们不应该与打印到物理屏幕或发射核武器,但经常purity == referentially transparent和参照透明的随机性将毫无用处 https://xkcd.com/221/.

random = 9 -- a referentially transparent random number

所以我们需要对随机性有一个不同的想法来使其纯粹。

II.

科学代码中用于增强再现性的典型“作弊”(非常重要)是修复实验的随机种子,以便其他人可以验证他们得到的结果完全相同的结果每次运行代码时。这正是引用透明度!我们来试试吧。

type Seed = Int
random :: Seed -> (Int, Seed)
random s = (mersenneTwisterPerturb s, splitSeed s)

where mersenneTwisterPerturb是一个伪随机映射Seeds to Int and splitSeed是一个伪随机映射Seeds to Seeds。请注意,这两个函数都是完全确定性的(并且引用透明),因此random也是如此,但我们可以像这样创建一个无限的、惰性的伪随机流

randomStream :: Seed -> [Int]
randomStram s = mersenneTwisterPerturb s : randomStream (splitSeed s)

同样,该流是确定性的,基于Seed值,但是只看到流而不看到种子的观察者应该无法预测其未来值。

III.

我们可以使用随机整数流来打乱列表吗?当然我们可以,通过使用模运算。

shuffle' :: [Int] -> [a] -> [a]
shuffle' (i:is) xs = let (firsts, rest) = splitAt (i `mod` length xs) xs
                     in (head rest) : shuffle' is (firsts ++ tail rest)

或者,为了使其更加独立,我们可以预先组合流生成函数以获得

shuffle :: Seed -> [a] -> [a]
shuffle s xs = shuffle' (randomStream s) xs

另一个“种子消耗”引用透明的“随机”函数。

IV.

所以这似乎是一个重复的趋势。事实上,如果你浏览该模块System.Random你会看到很多像我们上面写的那样的函数(我专门设计了一些类型类)

random :: (Random a) => StdGen -> (a, StdGen)
randoms :: (Random a) => StdGen -> [a]

where Random是可以随机生成的事物的类型类别StdGen是一种Seed。这已经是足够的实际工作代码来编写必要的洗牌函数。

shuffle :: StdGen -> [a] -> [a]
shuffle g xs = shuffle' (randoms g) xs

还有一个IO功能newStdGen :: IO StdGen这将让我们构建一个随机种子。

main = do gen <- newStdGen
          return (shuffle gen [1,2,3,4,5])

但你会注意到一些烦人的事情:如果我们想要制作,我们需要不断改变生成不同的随机排列

main = do gen1 <- newStdGen
          shuffle gen1 [1,2,3,4,5]
          gen2 <- newStdGen
          shuffle gen2 [1,2,3,4,5]

          -- using `split :: StdGen -> (StdGen, StdGen)`
          gen3 <- newStdGen
          let (_, gen4) = split gen3
          shuffle gen3 [1,2,3,4,5]
          let (_, gen5) = split gen4
          shuffle gen4 [1,2,3,4,5]

这意味着你要么必须做很多StdGen如果你想要不同的随机数,记账或留在 IO 中。这“有意义”,因为引用透明度再次——一组随机数必须是随机的相对于彼此因此您需要将每个随机事件的信息传递到下一个随机事件。

不过,这确实很烦人。我们可以做得更好吗?

V.

好吧,通常我们需要的是一种让函数接受随机种子然后输出一些“随机”结果和next seed.

withSeed :: (Seed -> a) -> Seed -> (a, Seed)
withSeed f s = (f s, splitSeed s)

结果类型withSeed f :: Seed -> (a, Seed)是一个相当普遍的结果。让我们给它起个名字

newtype Random a = Random (Seed -> (a, Seed))

我们知道我们可以创造有意义的Seeds in IO,所以有一个明显的函数可以转换Random类型为IO

runRandom :: Random a -> IO a
runRandom (Random f) = do seed <- newSeed
                          let (result, _) = f seed
                          return result

现在感觉我们已经得到了一些有用的东西——类型随机值的概念a, Random a只是一个函数Seeds 返回下一个Seed以便以后Random值不会全部相同。我们甚至可以制作一些机器来组合随机值并执行此操作Seed-自动通过

sequenceRandom :: Random a -> Random b -> Random b
sequenceRandom (Random fa) (Random fb) = 
    Random $ \seed -> let (_aValue, newSeed) = fa seed in fb newSeed

但这有点愚蠢,因为我们只是扔掉_aValue。让我们组合它们,使第二个随机数实际上很大程度上取决于第一个随机值。

bindRandom :: Random a -> (a -> Random b) -> Random b
bindRandom (Random fa) getRb = 
    Random $ \seed -> let (aValue, newSeed) = fa seed
                          (Random fb)       = getRb aValue
                      in fb newSeed

我们还应该注意到,我们可以做“纯粹”的事情Random值,例如,将随机数乘以 2:

randomTimesTwo :: Random Int -> Random Int
randomTimesTwo (Random f) = Random $ \seed -> let (value, newSeed) = f seed
                                              in (value*2, newSeed)

我们可以将其抽象为 Functor 实例

instance Functor Random where
  fmap f (Random step) = Random $ \seed -> let (value, newSeed) = step seed
                                           in (f value, newSeed)

现在我们可以创建很酷的随机效果,例如布朗运动

brownianMotion :: Random [Int]
brownianMotion = 
   bindRandom random $ \x -> 
       fmap (\rest -> x : map (+x) rest) brownianMotion

VI.

这触及了我一直在写的整个问题的核心。随机性可以存在于IOmonad 非常好,但它也可以作为一个更简单的对象单独存在Random单子。我们可以立即编写实例。

instance Monad Random where
  return x = Random (\seed -> (x, seed))
  rx >>= f = bindRandom rx f

因为它是一个单子,所以我们得到了自由do符号

brownianMotion' = do x <- random
                     rest <- brownianMotion'
                     return $ x : map (+x) rest

你甚至可以打电话给runRandom单子同态,但这是一个非常不同的话题。

所以,回顾一下

  1. 引用透明语言中的随机性需要Seeds
  2. carting Seed很烦人
  3. “提升”和“绑定”随机值有一个常见的模式,用于路由Seed自然而然地在身边
  4. 该模式形成一个单子

真正简短的答案是您可能想要使用random http://hackage.haskell.org/packages/archive/random/1.0.0.3/doc/html/System-Random.html甚至也许莫纳德随机 http://hackage.haskell.org/packages/archive/MonadRandom/0.1.3/doc/html/Control-Monad-Random.html来实施你的洗牌。通常,它们对于“采样”会派上用场。

Cheers!

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何打乱列表? 的相关文章

  • 测试列表是否已排序

    在 haskell 中找到最小列表确实很容易 foldl1 min 9 5 7 3 7 4 6 10 给我3 我更换了min with lt 测试列表是否已排序 foldl1 lt 9 5 7 3 7 4 6 10 我收到此错误消息 No
  • 结构上强制的自由替代,没有左派分配性

    有一个不错的免费替代品 http hackage haskell org package free 4 12 4 docs Control Alternative Free html在伟大的free包 它将函子提升到左分配替代方案 也就是说
  • 当单态限制打开*时,如何解决歧义问题?

    因此 在学习 Haskell 时 我很快就遇到了可怕的单态限制 在 ghci 中 Prelude gt let f print show Prelude gt f 5
  • Control.Arrow 与 Data.Tuple.Extra

    我经常使用以下功能Data Tuple Extra图书馆 first second and both 有等效的 函数Control Arrow 其实我更喜欢Data Tuple Extra因为我完全迷失了文档Control Arrow 使用
  • 绑定变量时 Haskell 中的无限循环

    下面的 Haskell 代码不会终止 有人可以解释一下为什么吗 谢谢 f let x 10 in let x x x in x 我认为解释器首先绑定 x 10 然后将 x x 计算为 100 并绑定 x 100 环境变为 x 100 那么整
  • Haskell:如何创建将函数应用于元组项的最通用函数

    这是一个个人练习 旨在更好地理解 Haskell 类型系统的局限性 我想创建最通用的函数 将某些函数应用于 2 条目元组中的每个条目 例如 applyToTuple fn a b fn a fn b 我试图让这个函数在以下每种情况下都起作用
  • 在 Haskell 中对单位的组成(例如英寸、美元等)进行建模

    跟进自我之前的一个问题 https stackoverflow com q 73375273 222529 我问如何创建一个可以对单元进行建模的类型 例如Inch 作为 Haskell 中的一种类型 我现在面临的问题是如何对该单元和其他单元
  • Haskell 单例:我们可以通过 SNat 获得什么

    我正在尝试使用 Haskell 单例 在论文中使用单例进行依赖类型编程 http cs brynmawr edu rae papers 2012 singletons paper pdf并在他的博客文章中单例 v0 9 发布 https t
  • 应用交换律

    带有效果的应用程序编程 http staff city ac uk ross papers Applicative html麦克布莱德和帕特森的论文提出了互换法 u lt gt pure x pure f gt f x lt gt u 为了
  • 计算/获取分层数据的“级别”

    好吧 我真的不知道这是否是正确的标题 但我不知道如何称呼它 我的问题是关于我的作业 我现在已经工作了几个小时 主题是 函数式数据结构 我有点陷入困境 我不知道如何继续 所以我需要编写一个具有以下签名的函数 data Heap e t Hea
  • 如何在 blaze-html 中渲染 blaze-svg 标记

    我想将使用 blaze svg 生成的 svg 图直接包含在使用 blaze html 生成的 html 中 两者都基于 blaze markup 所以我希望它很容易 diagram1 Svg diagram1 try1 Html try1
  • 表达式“ap zip tail”如何工作

    我想知道怎么写f x zip x tail x 点免费 所以我使用了pointfree程序 结果是f ap zip tail ap作为 Control Monad 的函数 我不明白点自由定义是如何工作的 如果我能从类型的角度去理解的话 希望
  • 如何在 Haskell 中枚举递归数据类型?

    这篇博文 http lukepalmer wordpress com 2008 05 02 enumerating a context free language 对于如何使用 Omega monad 对角枚举任意语法有一个有趣的解释 他提
  • 如何在 TH 拼接中复制 'name 的行为

    考虑这个 Haskell 文件 LANGUAGE TemplateHaskell OPTIONS GHC fplugin Test Inspection Plugin module Text main where import Test I
  • 'lens' 的阴谋集团依赖性解析失败

    我刚刚做了一个阴谋更新并尝试从 hackage 安装 lens 这给了我以下错误 cabal install j lens Resolving dependencies Configuring dlist 0 7 0 1
  • 如何获取常量内存中的统计数据

    我有一个函数 它会创建一些随机的数值结果 我知道 结果将是 a 小 a b 约 50 范围内的整数a b 我想创建一个执行上述函数 1000000 次的函数 并计算每个结果出现的频率 该函数使用随机生成器来生成结果 问题是 我不知道如何在常
  • 为什么haskell中的递归列表这么慢?

    我对 Haskell 很陌生 我在 Haskell 中定义了一个函数 febs Integral a gt a gt a febs n n lt 0 0 n 1 1 n 2 1 otherwise febs n 1 febs n 2 但是
  • 是否有一个基于对象身份的、线程安全的记忆库?

    我知道记忆化似乎是堆栈溢出的 haskell 标签上的一个长期话题 但我think以前没有人问过这个问题 我知道 Haskell 有几个不同的 现成 记忆库 memo combinators 和 memotrie 包 利用涉及惰性无限数据结
  • 在 haskell 中处理 IO 与纯代码

    我正在编写一个shell脚本 我在haskell中的第一个非示例 它应该列出一个目录 获取每个文件大小 进行一些字符串操作 纯代码 然后重命名一些文件 我不确定我做错了什么 所以有两个问题 我应该如何安排这样的程序中的代码 我有一个具体问题
  • 有没有办法在 Emacs 中使用 Djinn 自动生成 Haskell 代码?

    标题几乎说明了一切 我正在寻找这样的东西 f Int gt Bool gt Int f body Djinn 可以使用定理证明来通过证明该类型存在来生成此类函数的代码 我想知道 是否有现有的方法可以从 Emacs 中获取此功能 因此 我不需

随机推荐

  • 使用大数据集在 Google Colab TPU 上训练 seq2seq 模型 - Keras

    我正在尝试使用 Google Colab TPU 上的 Keras 训练用于机器翻译的序列到序列模型 我有一个可以加载到内存中的数据集 但我必须对其进行预处理才能将其提供给模型 特别是 我需要将目标单词转换为一个热向量 并且在许多示例中 我
  • 正在使用 PIL 保存损坏的图像

    我遇到一个问题 操作图像像素导致保存损坏的图像 因此 我使用 PIL 打开图像 然后将其转换为 NumPy 数组 image Image open myimage png np image np asarray image 然后 我转置图像
  • Google Cloud Platform (GCP) Cloud Shell“Boost”功能缺失

    当我今天打开 GCP Cloud shell 时 Boost 功能消失了 尝试了所有菜单 甚至尝试了此处给出的选项 通过 gcloud cli 启用 Google Cloud Shell Boost 模式 https stackoverfl
  • 嵌套循环结果

    我真的不知道如何找出嵌套循环的结果 例如 在下面的伪代码中 我无法弄清楚执行结束时会给出什么 如果有人给我一个简单的解决方案 我会很高兴 r lt 0 for i lt 1 to n do for j lt 1 to i do for k
  • SQL Server 中的 FIFO 查询

    我正在构建一个库存管理应用程序c with SQL server 我想做一个FIFO从我的表查询 我以可变价格购买了相同的产品 之后我卖掉了其中一些 我想根据 先进先出 进行查询BatchDate柱子 所以我想通过PurchasePrice
  • 如何将文件透明地传输到浏览器?

    受控环境 IE8 IIS 7 ColdFusion 当从 IE 发出指向媒体文件 例如 mp3 mpeg 等 的 GET 请求时 浏览器将启动关联的应用程序 Window Media Player 我猜测 IIS 提供文件的方式允许应用程序
  • 扩展构建器中的“映射到现有表”显示 TYPO3 中的奇怪问题

    在我的扩展中MyExt 我映射了模型Page to pagesTYPO3 中的表 首先它向我展示了type mismatch错误 无论如何我继续保存它 会发生以下情况 我的页面树变成这样 我的新记录表单仅显示 UID 而不显示标题 My P
  • 检查 Android 手机上的方向

    如何查看Android手机是横屏还是竖屏 当前配置用于确定要检索的资源 可从资源中获取Configuration object getResources getConfiguration orientation 您可以通过查看其值来检查方向
  • 将输入中每个单词的第一个字符设为大写

    我想知道如何在输入区域自动生成单词的第一个字符 目前我的代码是 Name
  • 如何在shell中输出返回码?

    我正在尝试通过调用自定义 shell 脚本sh bin sh c myscript sh gt log txt 2 gt 1 echo 该命令的输出是创建的后台进程的 PID 我想指导 bin sh保存返回码myscript sh到某个文件
  • 如何判断计算机是否已重新启动?

    我曾经使用过一个命令行 SMTP 邮件程序 作为试用版的限制 它允许您在每个 Windows 会话中最多接收 10 封电子邮件 如果您重新启动计算机 您可能还会收到 10 个以上 我认为这种共享软件破坏非常巧妙 我想在我的应用程序中复制它
  • 发送 POST 请求时 JSON 原语无效

    我有以下 ajax 请求 其中我尝试将 JSON 对象发送到服务器 function sendData subscriptionJson ajax type POST url Url Action SubscribeSecurities S
  • 在 Linux 上使用多处理时,TKinter 窗口不会出现

    我想生成另一个进程来异步显示错误消息 同时应用程序的其余部分继续 我正在使用multiprocessingPython 2 6 中的模块来创建进程 我试图用以下命令显示窗口TKinter 这段代码在Windows上运行良好 但在Linux上
  • Py2exe - Pmw WindowsError:[错误 3]

    我正在尝试使用 Py2exe 构建独立的可执行文件 我已经导入了 Pmw 类 当我运行独立可执行文件时 出现以下错误 Traceback most recent call last File py line 9 in
  • 在 bash 脚本中提取 XML 值 [重复]

    这个问题在这里已经有答案了 我正在尝试从 xml 文档中提取一个值 该文档已作为变量读入我的脚本中 原始变量 data is
  • 从 android 简单上传到 S3

    我在网上搜索了从 android 上传简单文件到 s3 的方法 但找不到任何有效的方法 我认为这是因为缺乏具体步骤 1 https mobile awsblog com post Tx1V588RKX5XPQB TransferManage
  • Spring Data 与 Spring Data JPA 与 JdbcTemplate

    我有信心Spring Data and Spring Data JPA指的是相同的 但后来我在 youtube 上观看了一个关于他正在使用JdbcTemplate在那篇教程中 所以我在那里感到困惑 我想澄清一下两者之间有什么区别Spring
  • jqgrid。改变主题

    如何在不更改样式表的情况下更改 jqgrid 的外观 基本上我使用 jqueryui 来设计我的网站 但我想为网格使用不同的背景图像 这可能吗 您是否想要将多个 jQueryUI 主题应用到同一页面 并让 jqgrid 使用其中一个主题 同
  • 使用 subprocess.Popen() 或 subprocess.check_call() 时程序卡住

    我想从 python 运行一个程序并找到它的内存使用情况 为此 我正在使用 l a out lt in txt gt out txt p subprocess Popen l shell False stdout subprocess PI
  • 如何打乱列表?

    如何从一组数字 1 2 3 直到我击中x 我的计划是重新调整列表 1 2 3 并把它砍在x chopAt 3 2 3 1 2 3 chopAt 3 2 1 3 2 1 3 chopAt 3 3 1 2 3 chopAt chopAt x y