[英]Create infinite list in Haskell with IO
编辑!
我正在尝试编写一个算法来生成一个(无限)梅森素数列表。 我有一个算法 (Rabin-Miller) 返回一个 IO Bool,根据算法是否认为数字是素数。 这个算法叫做 rabinMiller,它有两个参数,第一个是表示列表安全性的整数,第二个是我们提交给素性测试的数字。
我想索引所有素数(称为素数)的列表,对于素数中的每个 p,检查 rabinMiller 是否认为 2^p - 1 是素数。 如果是,我们将 2^p - 1 提交到列表中。
我现在拥有的是:
rbMersenneGen :: Integer -> IO(IO [Integer])
rbMersenneGen k = do return $ rbMersenneGens 0 k
rbMersenneGens :: Int -> Integer -> IO [Integer]
rbMersenneGens x k =
let n = primes!!x
m = (2^n) - 1
in do
prim <- rabinMiller k m
if prim then
m:rbMersenneGens (x + 1) k
else
rbMersenneGens (x + 1) k
但这并没有真正起作用,因为我无法正确获得m:rbMersenneGens (x + 1) k
。 我得到的错误是m
是一个Integer
而不是[Integer]
,然后整个m:rbMersenneGens (x + 1) k
是错误的并产生其他错误
你的原始类型很好; 我们只需要稍微调整rbMersenneGens
的定义。 我也会稍微重构一下这个函数。
rbMersenneGen :: Integer -> IO [Integer]
rbMersenneGen k = rbMersenneGens 0 k
rbMersenneGens :: Int -> Integer -> IO [Integer]
rbMersenneGens x k =
let n = primes!!x
m = (2^n) - 1
in do
prim <- rabinMiller k m
-- We call rmMersenneGens the same way in either case;
-- the only difference is which function we apply to the result
(if prim then (m:) else id) (rbMersenneGens (x+1) k)
您的问题是prim
需要是if-else
表达式的Bool
,而do
表达式需要计算为IO [Integer]
值。 这意味着rabinMiller
需要返回一个[Bool]
值,而不是它所做的IO Bool
。 解决方法是将if
else 替换为Data.Bool.bool :: a -> a -> Bool -> a
。
这不会类型检查...
rbMersenneGens :: Int -> Integer -> IO [Integer]
rbMersenneGens x k =
let n = primes!!x
m = (2^n) - 1
prim = rabinMiller k m -- IO Bool
in (bool id (m:) prim) (rbMersenneGens (x+1) k)
因为我们仍然试图将prim
视为Bool
而不是IO Bool
,但这确实:
rbMersenneGens :: Int -> Integer -> IO [Integer]
rbMersenneGens x k =
let n = primes!!x
m = (2^n) - 1
prim = rabinMiller k m
in (bool id (m:)) <$> prim <*> (rbMersenneGens (x+1) k)
if
与IO Bool
一起工作,我们不能使,但我们可以提升bool
与一个一起工作。 实际上,我们只需要将IO
视为Applicative
,而不是Monad
。 我们正在用fmap
(中缀形式<$>
)替换>>=
。
您在rbMersenneGens
有一个 do 块。 do 块的结果总是与里面的东西在同一个 monad 中。 由于您在内部调用rabinMiller
,它位于IO
monad 中,因此 do 块的结果也在IO
monad 中。 但是您已经声明rbMersenneGens
返回一个[Integer]
,它与推导的类型不匹配。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.