Haskell 让vs在一元值中执行

Haskell 让vs在一元值中执行,haskell,random,monads,let,Haskell,Random,Monads,Let,当试图处理一元值时,使用let或do有什么区别?(不确定这是否是正确的表达方式) 例如: --导入系统。随机 *Main>dupRand=let i=randomRIO(1,10)序列[i,i] *Main>:t dupRand dupRand::(随机a,数值a)=>IO[a] *Main>dupRand [8,3] *Main>dupRand [2,9] *Main>dupRand [9,5] *Main>dupRand2=doi:t dupRand2 dupRand2::(随机a,数值a)

当试图处理一元值时,使用
let
do
有什么区别?(不确定这是否是正确的表达方式)

例如:

--导入系统。随机
*Main>dupRand=let i=randomRIO(1,10)序列[i,i]
*Main>:t dupRand
dupRand::(随机a,数值a)=>IO[a]
*Main>dupRand
[8,3]
*Main>dupRand
[2,9]
*Main>dupRand
[9,5]
*Main>dupRand2=doi:t dupRand2
dupRand2::(随机a,数值a)=>IO[a]
*Main>dupRand2
[6,6]
*Main>dupRand2
[9,9]
*Main>dupRand2
[5,5]
为什么在
dupRand2
中,函数成功地复制了一个随机值,而在
dupRand
中,函数似乎只生成了两个随机值

dupRand =
  let i = randomRIO (1, 10)
  in sequence [i, i]
您将
i
绑定到
IO
操作,该操作在运行时将生成一个随机数。您将创建一个包含两个元素的列表,每个元素都包含该操作。现在

sequence
  :: (Traversable t, Monad m)
  => t (m a) -> m (t a)
在此上下文中,
可遍历的
[]
单子
IO
,因此

sequence :: [IO a] -> IO [a]
这样做的目的是在列表中运行每个
IO
操作,按顺序返回结果列表。因此,当我们运行序列[i,i]时,我们得到一个随机数,得到一个随机数,然后生成一个包含这两个数字的列表


dupRand2
不进行打字检查。我猜你的意思是

dupRand2 = do
  i <- randomRIO (1, 10)
  pure [i, i]

运行时,此操作将
i
绑定到一个随机数(而不是生成一个随机数的操作),然后返回一个重复两次
i
的列表。

dupRand2
不会按写的方式进行打字检查。也许你的意思是
pure[i,i]
dupRand2
也会为我抛出错误<代码> DuPrand < /Cord>给出了不同的随机值,因为你在说,考虑生成一个随机int的动作,现在考虑两次包含该动作的列表,现在顺序地按顺序运行该列表中的动作。这里的本质区别在于,
randomRIO(1,10)
是一个生成数字的“IO操作”,但不能保证每次都是相同的数字。虽然
i oops谢谢,但在
dupRand2
中,我的意思是
pure
而不是
sequence
,我认为这几乎完全重复了我在投票中提到的问题。如果你不同意,请随意指出不同之处,我将投票重新开放。明白了,谢谢。我想我仍然需要摆脱命令式思维模式,
=
就像haskell中的
bind
。这是否只是试图将
i
绑定到随机值的产物?i、 e.这是否意味着在
let i=
i@zli的情况下,
let x=e
几乎与
x相同(为什么“几乎相同”而不是“相同”有两个原因:
let
可以进行多态绑定,而
@DanielWagner,模式匹配失败也有不同的作用。哦,
x
是否打算代表任何模式,而不是特定的变量?我想如果你想谈论一般的模式,你会使用不同的元变量。无论如何,是的,c对于可反驳的模式,我们还有另一个区别。
dupRand2 =
  randomRIO (1, 10) >>= \i ->
    pure [i, i]