haskell - Haskell 中定义范围内的随机 double 列表?

标签 haskell random

如何制作符合定义范围的“Double”类型的随机数列表?对于像我这样的新手来说,关于这个问题的信息有点令人困惑。尝试类似的事情:

randomlist :: Int -> Int -> [IO Double]
randomlist a b = do
  g <- newStdGen
  return (randomRs (a,b) g)

失败,错误:

Couldn't match expected type `[t0]' with actual type `IO StdGen'

你能指出我的代码中的错误吗?

最佳答案

你几乎已经拥有它了。你有两个问题。主要问题是[IO Double]您的类型签名的一部分;这表示您将返回一个 IO 操作列表,每个操作都可以产生一个 double 值。相反,您想要返回 IO [Double] ——一个 IO 操作,运行时会生成无限的 double 列表。如果你只是改变它,你就差不多完成了;剩下的问题是你有 abInt s,但返回 Double s。如果你想返回 double ,你的界限必须是 double ,对于整数也是如此。 (要将 Int s 转换为 Double s,您可以使用 fromIntegral ;相反,您可以使用 round 。)因此,为了让您的代码正常工作,您需要更改的只是类型签名:

randomlist :: Double -> Double -> IO [Double]
randomlist a b = do
  g <- newStdGen
  return (randomRs (a,b) g)

事实上,如果您省略类型签名,一切都会好起来的; GHC 会推断出更通用的类型签名 Random a => a -> a -> IO [a] 。换句话说,您的函数适用于您可以生成随机成员的任何数据类型。

您还可以稍微简化您的代码。例如,以下内容是等效的:

randomlist :: Random a => a -> a -> IO [a]
randomlist a b = fmap (randomRs (a,b)) newStdGen

fmap :: Functor f => (a -> b) -> f a -> f b function 允许您在仿函数内应用普通函数。什么是仿函数?粗略地说,它是某种容器;输入函数,例如 [] , (r ->) ,和IO是示例。1 这正是您想要的; randomRs (a,b)类型为(Random a, RandomGen g) => g -> [a] ,而您需要给它类型 IO StdGen 的东西,得到 Random a => IO [a]返回。

还有一种方法可以让这个变得更好(这就是我写的方式)。如果您导入Control.Applicative ,你最终会得到

import Control.Applicative
randomlist :: Random a => a -> a -> IO [a]
randomlist a b = randomRs (a,b) <$> newStdGen

<$>fmap 的同义词;它看起来像 $ ,普通应用程序,因为它们几乎相同。 <$>只是将您提升为仿函数(此处为 IO )。

<小时/>

1:如果这不是很清楚,请不要担心;你可以在不完全理解它的细节的情况下使用这些东西,这最终会导致理解。

关于haskell - Haskell 中定义范围内的随机 double 列表?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6699277/

相关文章:

haskell - Prelude 中是否有一个函数可以将一个值与应用于函数的值配对?

haskell - 代数数据类型的特定用例

java - 从 Java Iterator 中随机跳过 'X' 百分比的单词

haskell - 如何在 Yesod 中进行(基于角色的)访问控制?

algorithm - Haskell 深度优先搜索图

haskell - 是否有用于编写词法分析器的 haskell EDSL?

Javascript - 从随机单词数组创建段落

function - 关于在函数和宏定义中使用结构文字

java - 如何显示一组随机单词?

matlab - 如何在matlab中生成整个可能范围内均匀分布的随机 float