簡體   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