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]