繁体   English   中英

使用 IO 在 Haskell 中创建无限列表

[英]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)

ifIO 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM