Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Haskell中IO Bool的列表理解_Haskell_Boolean_Monads - Fatal编程技术网

Haskell中IO Bool的列表理解

Haskell中IO Bool的列表理解,haskell,boolean,monads,Haskell,Boolean,Monads,我试图通过Miller-Rabin素性检查来检查Mersenne数,从而找到可能的Mersenne素数 如果mersennes是Mersenne数字的无限列表,我想做如下操作: probableMersennePrimes :: IO [Integer] probableMersennePrimes = [ n | n <- mersennes, primeMillerRabin n ] probableMersennePrimes::IO[整数] ProbableMersenneTim

我试图通过Miller-Rabin素性检查来检查Mersenne数,从而找到可能的Mersenne素数

如果
mersennes
是Mersenne数字的无限列表,我想做如下操作:

probableMersennePrimes :: IO [Integer]
probableMersennePrimes = [ n | n <- mersennes, primeMillerRabin n ]
probableMersennePrimes::IO[整数]
ProbableMersenneTime=[n | n IO Bool


作为一个附带问题,类型应该是
IO[Integer]
还是
[IO Integer]

您可以使用
管道中的
ListT
来流式处理无限数量列表:

import Control.Monad
import Data.Monoid
import Pipes

mersennes :: [Integer]
mersennes = undefined

primeMillerRabin :: Integer -> IO Bool
primeMillerRabin = undefined

probableMersennePrimes :: ListT IO Integer
probableMersennePrimes = do
    n        <- Select (each mersennes)
    continue <- lift (primeMillerRabin n)
    guard continue
    return n

main = runListT $ do
    n <- probableMersennePrimes
    lift (print n)
    mempty
import-Control.Monad
导入数据.幺半群
导入管道
梅森尼斯::[整数]
梅森尼斯=未定义
primeMillerRabin::整数->IO布尔
primeMillerRabin=未定义
probableMersennePrimes::ListIO整数
probableMersennePrimes=do

n如果将
primeMillerRabin
更改为
RandomGen g=>Integer->State g Bool
类型,则可以使用
filterM
执行此操作

probableMersennePrimes :: RandomGen g => g -> [Integer]
probableMersennePrimes = evalState $ filterM primeMillerRabin mersennes
通过使用
evalState
,我们放弃了
filterM primemillerabin mersennes
计算的最终状态,因此我们不能严格要求它。但这是一件好事,因为最终状态只有在我们到达
mersennes
列表的末尾后才可用,它是无限的,没有尽头

这允许计算惰性地生成
probableMersennePrimes gen
的元素

由于随机数生成器的工作方式,当它返回一个
IO
操作时,您不能这样做。IO计算需要知道结束状态是什么,这样它才能在计算之后生成另一个随机数,因此它必须无休止地循环,寻找无尽列表的结尾

但不要只是相信我,试试看:

module SO26307073 where
import Control.Monad.State
import System.Random

-- find how many times a factor divides a number
-- (p^s * d) `factorBy` p == (s,d) iff d `rem` p /= 0
factorBy :: Integral a => a -> a -> (Int,a)
factorBy n p = (length steps - 1, fst $ last steps)
  where steps = takeWhile ((==0) . snd) $ iterate (flip quotRem 2 . fst) (n, 0)

mersennes :: Num a => [a]
mersennes = [ 2^n - 1 | n <- [2..] ]

type RandomRM m = (Integer, Integer) -> m Integer

primeMillerRabinWith :: Monad m => RandomRM m ->  Integer -> m Bool
primeMillerRabinWith randomRM n = do
  let nMinus1 = n-1
      (s,d) = nMinus1 `factorBy` 2
  liftM (all id) . replicateM 10 $ do
    a <- randomRM (2, nMinus1)
    let x = (a^d) `mod` n
    let xs = take s $ iterate (\x -> (x^2) `mod` n) x
    return $ x == 1 || any (== nMinus1) xs

probableMersennePrimesWith :: Monad m => RandomRM m -> m [Integer]
probableMersennePrimesWith randomRM = filterM (primeMillerRabinWith randomRM) mersennes

probableMersennePrimesPure :: RandomGen g => g -> [Integer]
probableMersennePrimesPure = evalState . probableMersennePrimesWith $ state . randomR

probableMersennePrimesIO :: IO [Integer]
probableMersennePrimesIO = probableMersennePrimesWith $ randomRIO

所有其他答案都很好。但是,我认为解决这个问题最简单的方法是惰性IO,值得考虑。我还认为在这种特殊情况下,惰性IO是无害的,因为它不涉及系统资源(文件句柄等)

您只需要为惰性IO重新定义一个特殊的
filterM

import System.IO.Unsafe (unsafeInterleaveIO)

filterMIO :: (a -> IO Bool) -> [a] -> IO [a]
filterMIO p = go
  where
    go []     = return []
    go (x:xs) = do
      xs' <- unsafeInterleaveIO (go xs)
      b   <- p x
      return $ if b then (x:xs') else xs'

probableMersennePrimes :: IO [Integer]
probableMersennePrimes = filteMIO primeMillerRabin mersennes
import System.IO.Unsafe(unsafeInterleaveIO)
filterMIO::(a->IO Bool)->[a]->IO[a]
filterMIO p=go
哪里
go[]=return[]
go(x:xs)=do

为什么这是IO?素数检查器不应该是纯的吗?这是一个概率素数检查器。好的。如果IO是必要的,我会选择@cirdec-answer。
import System.IO.Unsafe (unsafeInterleaveIO)

filterMIO :: (a -> IO Bool) -> [a] -> IO [a]
filterMIO p = go
  where
    go []     = return []
    go (x:xs) = do
      xs' <- unsafeInterleaveIO (go xs)
      b   <- p x
      return $ if b then (x:xs') else xs'

probableMersennePrimes :: IO [Integer]
probableMersennePrimes = filteMIO primeMillerRabin mersennes