gpt4 book ai didi

random - 从数组或列表中随机选取元素

转载 作者:行者123 更新时间:2023-12-02 00:04:42 25 4
gpt4 key购买 nike

免责声明:我使用的是 PureScript,但也添加了 Haskell 标签,因为我认为这在两种语言中的行为方式可能相同,而且 Haskell 社区更大。

我想从数组中随机选取一个元素,重复。每次我都期待一个新的随机选择,但重复调用的值总是相同的。随机函数似乎在每次运行程序时只被评估一次。

这总是在后续调用中返回相同的名称:

import Data.Array (length, unsafeIndex)
import Effect.Random (randomInt)
import Effect.Unsafe (unsafePerformEffect)
import Partial.Unsafe (unsafePartial)

pick :: forall a. Array a -> a
pick arr = unsafePartial $ unsafeIndex arr i where
i = unsafePerformEffect $ randomInt 0 (length arr - 1)

name :: String
name = pick names

有了这个解决方法,它每次都会返回一个新的随机选择:

import Data.Array (length, unsafeIndex)
import Effect.Random (randomInt)
import Effect.Unsafe (unsafePerformEffect)
import Partial.Unsafe (unsafePartial)

pick :: forall a. Array a -> a
pick arr = unsafePartial $ unsafeIndex arr i where
i = unsafePerformEffect $ randomInt 0 (length arr - 1)

-- without the dummy argument, this is not re-evaluated
-- on subsequent calls and always returns the same name
name :: Unit -> String
name _ = pick names

我正在使用 Data.Array , Effect.Random , Effect.UnsafePartial.Unsafe .

我觉得这是一个丑陋的 hack。实现这一目标的正确方法是什么?

最佳答案

每次调用它时执行不同操作的函数与 Haskell 的设计相反,我认为 PureScript 也是如此,基于您必须导入的名称“Effect.Unsafe”。不通过使用 Unsafe 包中的东西来“欺骗”地编写这样的函数是不可能的,任何与这样的函数交互的人都会头疼。

相反,为您的函数提供更诚实的类型签名。我不知道 PureScript 的等价物,但在 Haskell 中它会是这样的(改编自 Get a random list item in Haskell ):

pick :: [a] -> Maybe (IO a)
pick [] = Nothing
pick xs = Just $ do
i <- randomRIO (0, len)
pure $ xs !! i
where len = length xs - 1

首先,您承认如果给定一个空列表,该函数实际上无法从列表1 中生成一个项目。然后,您承认这不是一个纯函数:您必须执行 IO(也许 PureScript 称之为 Effect?)来随机选择。现在调用者知道这两种影响,并且必须处理它们:检查是否为空并将其视为 IO 操作而不是纯值。


1 作为 Parse, don't validate争辩说,让你的函数接受一个 NonEmpty a 而不是接受 [a] 并返回一个 Maybe 实际上会更好,但我不想引入新的依赖项在这里。

关于random - 从数组或列表中随机选取元素,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60960707/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com