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