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