让vs以单调的价值观去做

zli*_*zli -1 random monads haskell let

使用letdo尝试使用Monadic值有什么区别?(不确定这是否是表达它的正确方法)

例如:

--import System.Random

*Main> dupRand = let i = randomRIO (1, 10) in sequence [i, i]
*Main> :t dupRand
dupRand :: (Random a, Num a) => IO [a]
*Main> dupRand
[8,3]
*Main> dupRand
[2,9]
*Main> dupRand
[9,5]

*Main> dupRand2 = do i <- randomRIO (1, 10); pure [i, i]
*Main> :t dupRand2
dupRand2 :: (Random a, Num a) => IO [a]
*Main> dupRand2
[6,6]
*Main> dupRand2
[9,9]
*Main> dupRand2
[5,5]
Run Code Online (Sandbox Code Playgroud)

为什么在中dupRand2,该函数成功复制了一个随机值,而在中dupRand,该函数看起来好像它生成了两个随机值?

dfe*_*uer 5

dupRand =
  let i = randomRIO (1, 10)
  in sequence [i, i]
Run Code Online (Sandbox Code Playgroud)

您绑定i了一个IO动作,该动作在运行时会产生一个随机数。您列出了两个元素的列表,每个元素都包含该动作。现在

sequence
  :: (Traversable t, Monad m)
  => t (m a) -> m (t a)
Run Code Online (Sandbox Code Playgroud)

在这种情况下,Traversableis []Monadis是IO,因此

sequence :: [IO a] -> IO [a]
Run Code Online (Sandbox Code Playgroud)

这样做是IO在列表中运行每个动作,并按顺序返回其结果列表。因此,当我们运行时sequence [i, i],我们得到一个随机数,得到一个随机数,然后生成两个列表。

dupRand2不进行类型检查。我猜你的意思是

dupRand2 = do
  i <- randomRIO (1, 10)
  pure [i, i]
Run Code Online (Sandbox Code Playgroud)

这是语法糖

dupRand2 =
  randomRIO (1, 10) >>= \i ->
    pure [i, i]
Run Code Online (Sandbox Code Playgroud)

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

  • (为什么“几乎相同”而不是“相同”?两个原因:`let`可以进行多态绑定,而`&lt;-`是单态的;以及`let`可以进行递归绑定,而默认情况下`x &lt;-fx要么是范围错误,要么只是将现有的x替换为新的x。) (2认同)