Haskell monad:IO[Double]到[IO Double]

Haskell monad:IO[Double]到[IO Double],haskell,random,io,monads,Haskell,Random,Io,Monads,考虑以下用于打印随机数的代码: import System.Random.Mersenne main = do g <- (newMTGen Nothing) xs <- (randoms g) :: IO [Double] mapM_ print xs import System.Random.mersene 主要= 如果您遇到分段错误,并且您没有使用FFI或任何以其名义使用unsafe的函数,在任何情况下,这并不奇怪!这意味着GHC存在漏洞,或者您正在使

考虑以下用于打印随机数的代码:

import System.Random.Mersenne

main =
 do g <- (newMTGen Nothing)
    xs <- (randoms g) :: IO [Double]
    mapM_ print xs  
import System.Random.mersene
主要=

如果您遇到分段错误,并且您没有使用FFI或任何以其名义使用
unsafe
的函数,在任何情况下,这并不奇怪!这意味着GHC存在漏洞,或者您正在使用的库正在执行不安全的操作

mapM\uprint
打印出无限多个
Double
s是非常好的;列表将以增量方式处理,程序应以恒定的内存使用率运行。我怀疑您正在使用的
System.Random.Mersenne
模块中存在错误,或者它所基于的C库中存在错误,或者您的计算机存在问题(例如RAM故障)。请注意,此警告附带:

由于当前的SFMT库极不纯净,目前每个程序只允许一个生成器。重新初始化它的尝试将失败

您最好使用提供的

也就是说,你不能用那种方式将
IO[Double]
转换成
[IO Double]
;如果不执行
IO
操作,就无法知道结果列表会有多长,这是不可能的,因为您有一个纯结果(尽管恰好包含
IO
操作)。对于无限列表,您可以编写:

desequence :: IO [a] -> [IO a]
desequence = desequence' 0
  where
    desequence n m = fmap (!! n) m : desequence (n+1) m
但每次执行此列表中的操作时,
IO[a]
操作都会再次执行;它只会丢弃列表中的其余部分

之所以
randoms
可以工作并返回无限多个随机数列表,是因为它将惰性IO与
unsafeInterleaveIO一起使用。(请注意,尽管名称中有“不安全”,但此名称不会导致SEGFULTS,因此还有其他原因。)

1其他不太可能的可能性包括C库的错误编译或GHC中的错误

假设我只想打印xs的前十个值。我怎么能这么做

只需使用
take

main =
 do g <- (newMTGen Nothing)
    xs <- (randoms g) :: IO [Double]
    mapM_ print $ take 10 xs  

顺便提一下,IO[Double]->[IO Double]本质上是“序列”的反向类型签名。听起来像是某种错误的编译或硬件问题,然后。。。您可能需要运行检查。您可以执行
IO[Double]->IO[IO Double]
。。。除非你
unsafePerformIO
。这种离奇的
-}
是很不寻常的。丹尼尔,代码对你来说正常吗?而且}是一个打字错误,只是为了记录在案,我认为提问者的电脑可能出了问题,而不是图书馆;所提供的代码对我来说没有故障。+1表示“您无法将
IO[Double]
转换为
[IO Double]
…如果不执行IO操作,无法知道结果列表的长度”,因此无法仅访问前十个列表元素。@Gautam:当然,只需在结果列表中使用
take
mapM_uuu.print(take 10 xs)
。这不会回答一个直接的问题(大约10个值),也无法纠正OP对该类型的基本误解,而是讨论一个错误的问题,就好像它在这里有价值一样。(-1)
main =
  do g <- newMTGen Nothing
     ys <- liftM (take 10) $ randoms g :: IO [Double]
     mapM_ print ys