随机数生成器函数返回Haskell中的嵌套元组

发布于 2025-01-27 20:24:35 字数 458 浏览 3 评论 0原文

我试图理解为什么我的Haskell功能会返回一个嵌套的元组,而我似乎无法围绕问题。

我具有生成随机二进制INT的此功能

test :: StdGen -> (Int, StdGen)
test g = do
  let (i, g') = randomR (0, 1) g
  return (i, g')

,但是,除非我更改功能以返回嵌套元组的功能,否则我无法对此进行编译,例如:

test :: StdGen -> (Int, (Int, StdGen))

如果这样做,我必须将SND元素在返回的元组中获取,以获取期望的结果:

g = mkStdGen 5
(i, g') = snd test g

如何使我的测试功能返回带有随机二进制和新生成器(I,G)的单个元组?我想念什么?

I am trying to understand why my haskell function returns a nested tuple, and I cannot seem to wrap my head around the problem.

I have this function that generates a random binary Int

test :: StdGen -> (Int, StdGen)
test g = do
  let (i, g') = randomR (0, 1) g
  return (i, g')

However, I cannot compile this unless I change the function to return a nested tuple, like so:

test :: StdGen -> (Int, (Int, StdGen))

If I do so, I have to get the snd element in the returned tuple, to get the desired result:

g = mkStdGen 5
(i, g') = snd test g

How do I make my test function return a single tuple with the random binary and a new generator (i, g)? What am I missing?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

风流物 2025-02-03 20:24:35

与其他语言不同,其中return是一个关键字,意味着立即退出过程并将值交给呼叫者,in Haskell return只是另一个功能,它可以做相当任意的事情。在Haskell中,选择将什么值交给呼叫者的方式就是简单地将其作为 值在等价符号的右侧。因此,删除返回使您的代码起作用:

test :: StdGen -> (Int, StdGen)
test g = do
  let (i, g') = randomR (0, 1) g
  (i, g')

但是,这种拼写方式test有点误导。大多数Haskell程序员仅在与Monadic操作员一起工作时使用do(命名return,偶然地,和(>>> =))并想要更好的语法。您不是在这里这样做;该代码对明智的东西的事实可能会让一些读者感到惊讶。相反,我建议明确使用它的代码,它甚至不再使用:

test g =
  let (i, g') = randomR (0, 1) g
  in (i, g')

此外,此net x = ... in x in x 可能只是用的内容写成x

test g = randomR (0, 1) g

作为美学,有些人会降低这一点(有些人不会 - 我对此建议的更改的依恋要少得多):

test = randomR (0, 1)

Unlike other languages, where return is a keyword that means to immediately exit a procedure and hand off a value to the caller, in Haskell return is just another function, and it can do fairly arbitrary things. In Haskell, the way to choose what value to hand off to the caller is to simply state it as the value on the right-hand side of an equals sign. So, deleting return makes your code work:

test :: StdGen -> (Int, StdGen)
test g = do
  let (i, g') = randomR (0, 1) g
  (i, g')

However, this way of spelling test is a little misleading. Most Haskell programmers use do only when they are working with the monadic operators (named return, coincidentally, and (>>=)) and want a better syntax for them. You are not doing that here; the fact that this code desugars to something sensible would probably surprise some readers. Instead, I recommend explicitly using the code that it desugars to, which isn't even longer:

test g =
  let (i, g') = randomR (0, 1) g
  in (i, g')

Additionally, this let X = ... in X is probably better just written with the content of the definition of X:

test g = randomR (0, 1) g

As a matter of aesthetics, some people will eta reduce this (and some won't -- I am a lot less attached to this suggested change than the previous ones):

test = randomR (0, 1)
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文