【发布时间】:2011-03-04 15:35:37
【问题描述】:
我有一个包含许多素数的文件。
我想写一个具有以下功能的模块:
module Primes as
( init,
primes,
is_prime)
where ...
init 应该在哪里读取文件并初始化应该是列表的素数和 is_prime。 我的问题是,我该怎么写?有没有办法“隐藏” IO monad?
更一般地说,我相信我像 OO 程序员一样思考。处理这个问题的好方法是什么?
【问题讨论】:
我有一个包含许多素数的文件。
我想写一个具有以下功能的模块:
module Primes as
( init,
primes,
is_prime)
where ...
init 应该在哪里读取文件并初始化应该是列表的素数和 is_prime。 我的问题是,我该怎么写?有没有办法“隐藏” IO monad?
更一般地说,我相信我像 OO 程序员一样思考。处理这个问题的好方法是什么?
【问题讨论】:
“隐藏” IO monad 的方法是将isPrime(以及任何其他使用素数列表的函数)编写为纯函数,并且仅在您可能需要时才引入 IO。您正在使用预先生成的素数列表并从文件中读取它们的事实只是一个实现细节,与处理素数的一般函数无关。
这是一个纯isPrime 的简单实现,它需要一个整数来测试和一个素数列表。请注意,它并不关心素数列表来自哪里,它只是一个整数列表。
isPrime :: Integer -> [Integer] -> Bool
isPrime n ps = n `elem` ps
现在让我们介绍一个从磁盘读取素数的函数。它的返回类型必须在 IO monad 中,因为我们正在执行 I/O。
readPrimesFromFile :: String -> IO [Integer]
readPrimesFromFile filename = ...
现在我们可以将此函数与isPrime 函数结合使用。一旦我们开始使用readPrimesFromFile,我们就会永远被“困”在 IO monad 中。
main :: IO ()
main = do
primeList <- readPrimesFromFile "primes.txt"
let result = isPrime 123 primeList
print result
【讨论】:
为什么你从一个素数文件开始呢?读取文件的 IO 时间可能比从头开始生成素数要慢。
请参阅 Data.Numbers.Primes 了解 (afaik) 生成所有素数列表的最有效方法。
【讨论】: