相关疑难解决方法(0)

Haskell的mapM不是懒惰吗?

更新:好的,这个问题可能非常简单.

q <- mapM return [1..]
Run Code Online (Sandbox Code Playgroud)

为什么这永远不会回来?


mapM是不是懒得处理无限列表?

下面的代码挂起.但是,如果我用线B替换A线,它就不会再挂起了.或者,如果我在A行之前加上"splitRandom $",它也不会挂起.

Q1是:mapM不是懒惰的吗?否则,为什么用线B替换A行"修复此"代码?

Q2是:为什么前面的A行与splitRandom"解决"了这个问题?

import Control.Monad.Random
import Control.Applicative

f :: (RandomGen g) => Rand g (Double, [Double])
f = do
    b <- splitRandom $ sequence $ repeat $ getRandom
    c <- mapM return b -- A
    -- let c = map id b -- B
    a <- getRandom
    return (a, c)

splitRandom :: (RandomGen g) => Rand g a -> Rand g a
splitRandom code = evalRand code <$> getSplit

t0 …
Run Code Online (Sandbox Code Playgroud)

monads haskell lazy-evaluation

18
推荐指数
3
解决办法
2961
查看次数

Haskell中的mapM是否严格?为什么这个程序会出现堆栈溢出?

以下程序正确终止:

import System.Random

randomList = mapM (\_->getStdRandom (randomR (0, 50000::Int))) [0..5000]

main = do
  randomInts <- randomList
  print $ take 5 randomInts
Run Code Online (Sandbox Code Playgroud)

运行:

$ runhaskell test.hs
[26156,7258,29057,40002,26339]
Run Code Online (Sandbox Code Playgroud)

但是,为它提供无限列表,程序永远不会终止,并且在编译时,最终会产生堆栈溢出错误!

import System.Random

randomList = mapM (\_->getStdRandom (randomR (0, 50000::Int))) [0..]

main = do
  randomInts <- randomList
  print $ take 5 randomInts
Run Code Online (Sandbox Code Playgroud)

跑步,

$ ./test
Stack space overflow: current size 8388608 bytes.
Use `+RTS -Ksize -RTS' to increase it.
Run Code Online (Sandbox Code Playgroud)

我希望getStdRandom每次从列表中选择一个项目时,程序都会懒洋洋地评估,在完成5次之后完成.为什么要评估整个列表?

谢谢.

有没有更好的方法来获得无限的随机数列表?我想将此列表传递给纯函数.

编辑:更多阅读揭示了该功能

randomList r = do g <- getStdGen
                  return …
Run Code Online (Sandbox Code Playgroud)

monads haskell lazy-evaluation

8
推荐指数
2
解决办法
1458
查看次数

标签 统计

haskell ×2

lazy-evaluation ×2

monads ×2